lundi 30 juillet 2018

copy constuctor of templated class does not always work for newer gcc

I am maintaining some legacy C++ code, which worked fine so far. Recently I switched from Ubuntu 16.04 (gcc 5.4) to Ubuntu 18.04 (gcc 7.3) and the code did not compile anymore (With clang 6.0 it did however). I am pretty sure it is c++ version thing. I have made changes to the code and it compiles now, but I would like to have some explanation of what is going on exactly.

The culprit is the copy constructor of the following fast hash map class

template< typename Key, typename Val, size_t (*hashf)(Key const &), typename KeyCompare = std::equal_to<Key> >
class fhash_map
{
public:
  fhash_map(fhash_map const & copy);
}

Now there is some other class, let's call it UseFull, which has various fhash_map members (I call this Variant A)

class UseFull: public UseFullParent
{
private:
  fhash_map<A, B, C> _this_works;
  fhash_map<A, Spline*, C> _this_does_not_work;
  fhash_map<A, std::vector<Spline*>, C> _neither_does_this;
public:
  UseFull(UseFull const & copy)
  : UseFullParent(copy)
  {
    _this_works(copy._this_works);
    _this_does_not_work(copy._this_does_not_work);
    _neither_does_this(copy._neither_does_this);
  }
}

With gcc 7.3 this fails to compile with the messages

error: no match for call to ‘(UseFull<A, Spline*, C>) (UseFull<A, Spline*, C>&)’
error: no match for call to ‘(UseFull<A, std::vector<Spline*>, C>) (UseFull<A, std::vector<Spline*>, C>&)’

Note that the compiler only complains about the to latter members (as indicated by their names), not about the first member (_this_works).

If I now change the copy constructor (Variant B) of the UseFull class to read

  UseFull(UseFull const & copy)
  : UseFullParent(copy)
  ,_this_works(copy._this_works);
  ,_this_does_not_work(copy._this_does_not_work);
  ,_neither_does_this(copy._neither_does_this);
  {
  }

It works fine.

My questions are:

  1. why does Variant A work with an older gcc and not with a newer
  2. what could be so special about some of the members? Is it the Spline class? What could be going on there (It seems pretty normal to me)
  3. what exactly is the difference between Variant A and Variant B? (That makes the difference in this case)

Aucun commentaire:

Enregistrer un commentaire