Search code examples
c++c++11boost-graphicc

icpc error implicitly generated assignment operator cannot copy reference member (boost graph)


I am using a boost::filter_iterator to filter over of a pair of boost graph vertices as follows:

I have a range of graph vertices using a vertex_iterator pair <vbegin, vend>. I want to filter the range using a predicate and the range needs to be grouped into say 4 sub-ranges

<begin1, end1> ... <begin4, end4>

So I filter over the vertex iterator using boost::filter_iterator and create 4 subranges. Such subrange iterator pairs need to be inserted into a container (vector)

std::vector< pair<filter_iterator, filter_iterator> >  my_vector
size of vector = 4 (because 4 pairs are inserted)

A filter predicate with a given desired parameter helps define the filter iterator range

<fbegin, fend>

The code is as below :

 template<typename Graph> 
 struct my_filter_pred {
   public:
     my_filter_pred() { }  
     my_filter_pred(Graph& _G, int _value) : G(_G), value(_value) {  } 

     template<typename vertex_t>
     bool operator() (vertex_t vertex) {

        //get property "p" of vertex in graph G
        auto p = get (mypropertytype, vertex, G);
        return (p.val == value); 
     }

     private: 
      Graph& G;
    }

  //get all vertices using vertex iterator
  vertex_iterator  vbegin, vend;
  boost::tie(vbegin, vend) = boost::vertices(G); 

The for - loop is as below"

  //for each i = 0,1,2,3 -> create a predicate with i as parameter.
  //apply the filter predicate over the vertex_iterator range
  //insert in the begin, end pair into vector

  for (int i=0; i<4; ++i) 
  {
    //for each i, create a filter_pred 
    my_filter_pred <Graph> filter_pred(G, i)

    //now create begin and end filter iterators as follows
    auto fbegin = boost::make_filter_iterator< my_filter_pred<Graph>,
                                       vertex_iterator>   (filter_pred, vbegin, vend)
    auto fend = boost::make_filter_iterator< my_filter_pred<Graph>,
                                       vertex_iterator>   (filter_pred, vend, vend)

    //fbegin, fend are of type filter iterator
    //insert the iterator pair into vector
    my_vector.push_back( std::make_pair (fbegin, fend) );
   }

Now: the problem testing part:

I am using 2 compilers gcc4.9 and Inter 13.0.1 for testing this code.

Results :

gcc 4.9 --> works correctly, compiles fine and works fine as well. 
icpc gives me the following error:

   error: implicitly generated assignment operator cannot copy:
        reference member "my_filter_pred <Graph>::G [with ... ]"

struct my_filter_pred { ^ detected during:

I googled the error and I found this link on intel's website here which describes about the same error but no information is provided for such error.

How do I solve this ? I tried adding the following into my predicate (function object)

   my_filter_pred& operator=(const my_filter_pred&);
   my_filter_pred(const my_filter_pred&);

but after that I get "undefined reference to .... " error. How do I explicitly define the copy assignment operator and copy constructor


Solution

  • Since you use a reference Graph& G in your predicate my_filter_pred the latter is copy-constructable but cannot be assigned by operator=. But you need operator = in many places of your code.gnable.

    I would recommend to change the code as follows

    template struct my_filter_pred { public: my_filter_pred() { }
    my_filter_pred(Graph& _G, int _value) : G(&_G), value(_value) { }

     template<typename vertex_t>
     bool operator() (vertex_t vertex) {
    
        //get property "p" of vertex in graph G
        auto p = get (mypropertytype, vertex, *G);
        return (p.val == value); 
     }
    
     private: 
      Graph* G;
    }
    

    Now filter predicate is copy-assignable.