c++stdvectorboost-variantapply-visitor

retrieving objects from boost::variant


I tried to ask my question before, but I think the way I ask my question is not proper. so I tried again here: (still I don't know what subject would be appropriate)

first I defined

typedef boost::variant<point, Line, Vertex> vec_variant;
typedef std::vector<vec_variant> vec;

the I write my function such that depends on the case it returns point, line, Vertex or even a combination of them.

vec my_func::select_T(const mesh::section& s, const char* model) const
{
  vec new_vec;
  .
  .
  .
  .
 //loop over my lines
  else if ( strcmp(model , "Line") == 0 )
  {
    for(section::lineIterator ite = s.beginLine(); ite != s.endLine(); ++ite )
    {
      Line ed = *ite;
        Point p0 = ed.point(0);
        Point p1 = ed.point(1);
        Point p0_modified ( /* some modification */  );
        Point p1_modified ( /* some modification */  ); 

        if( /* some other conditions */ )
        {
          new_vec.push_back(ed);
          new_vec.push_back(p0_modified); //note before pushing back any point 
          new_vec.push_back(p1_modified); //first I pushed back line
        }

         else if ( /* some other conditions */ )
         {
           .
           .
           .
           vertex m = .......;
           new_vec.push_back(ed);
           new_vec.push_back(m);  //note before pushing back any point 
                                  //first I pushed back line
         }
      }
    }
  }
      return new_vec;
    }

so at the end we may have something like this {ed, p0_modified, p0_modified, ed, m, ed, m, ed, p0_modified, p0_modified, ed, m, ....} {Line,Point,Point,Line,Vertex,line,Vertex,Line,Point,Point,Line,Vertex, ...}

Now I call this function in the other part of the code (different file)

first I defined a visitor:

    template<typename T>
    struct T_visitor : public boost::static_visitor<>
    {
       T_visitor(std::vector<T>& v) : zeroVector(v) {}
       template<typename U>
       void operator () (const U&) {}
       void operator () (const T& value)
       {
          zeroVector.push_back(value);
       }
    private:
       std::vector<T>& zeroVector;
    };

I called above function here :

void func_2( /*......*/ )
{
  . //we can use above visitor to store each type (point, line, Vertex) in vactor<point or line or Vertex)
  . //we do not know what the new_vec is at the end of the loop. the only thing we know is that after each line there
  . //would be either two points or one vertex
  .
  const char *model = "Edge";
  .
  .//How to find line ed and corresponded points?
  .
  create_line( Point& p0_modified, Point& p1_modified, Line& ed);    //two modified points and line
  .
  .//How to find point m and corresponded line?
  .
  create_point( m(0), m(1), m(2), Line& ed);    //point m coordinates and line
  .
  .
}

Solution

  • So your data structure is currently a sequence of Point, Line, and Vertex objects (I'm going to assume that the Surface in the first sentence is a typo). You also know the additional restriction that any Line must be followed either by two Points or one Vertex. Now you want to use this structure.

    This is possible, but it's also annoying. May I recommend that you simply change your data structure?

    struct LineWithPoints {
      Line line;
      Point p1, p2;
    };
    struct LineWithVertex {
      Line line;
      Vertex v;
    };
    typedef boost::variant<LineWithPoints, LineWithVertex> vec_variant;
    typedef std::vector<vec_variant> vec;
    

    And change your code to produce this sequence instead. Then working with it becomes trivial.