lundi 29 février 2016

Error in constructor receiving two parameters by value

Sometimes I find very useful, for simplicity and efficiency, using this type of iterator:

// Chunk 1
    template <class Itor1, class Itor2 = Itor1>
class Pair_Iterator
{
  Itor1 it1;
  Itor2 it2;

public:

  Pair_Iterator(Itor1 i1, Itor2 i2) : it1(i1), it2(i2) {}

  bool has_curr() const { return it1.has_curr() and it2.has_curr(); }

  auto get_curr() const
  {
    return std::make_pair(it1.get_curr(), it2.get_curr());
  }

  void next()
  {
    it1.next();
    it2.next();
  }
};

The idea is to traverse simultaneously two containers, which may be of different types, through its iterators.

Now, for a reason I do not manage not understand, the next test does not compile:

// previous chunk could be included here
struct It1
{
  It1() {}
  bool has_curr() const { return true; }
  int get_curr() const { return 1; }
  void next() {}
};

int main()
{
  for (Pair_Iterator<It1> it(It1(), It1()); it.has_curr(); it.next())
    ;
}

clang compiler (version 3.8) says:

error: member reference base type 'Pair_Iterator<It1> (It1 (*)(), It1 (*)())'
      is not a structure or union
  for (Pair_Iterator<It1> it(It1(), It1()); it.has_curr(); it.next())
                                            ~~^~~~~~~~~
it.C:57:62: error: member reference base type 'Pair_Iterator<It1> (It1 (*)(), It1 (*)())'
      is not a structure or union
  for (Pair_Iterator<It1> it(It1(), It1()); it.has_curr(); it.next())
                                                       ~~^~~~~

And gnu compiler (version 5.3) says:

error: request for member ‘has_curr’ in ‘it’, which is of non-class type ‘Pair_Iterator<It1>(It1 (*)(), It1 (*)())’
   for (Pair_Iterator<It1> it(It1(), It1()); it.has_curr(); it.next())
                                                ^
it.C:57:63: error: request for member ‘next’ in ‘it’, which is of non-class type ‘Pair_Iterator<It1>(It1 (*)(), It1 (*)())’
   for (Pair_Iterator<It1> it(It1(), It1()); it.has_curr(); it.next())

However, if I change the Pair_Iterator instantiation by:

It1 it1;
for (Pair_Iterator<It1> it(it1, It1()); it.has_curr(); it.next())

then everything compiles perfectly.

So my question would be:

  1. Why the first instantiation is invalid (I presume that because two compilers reject it)
  2. Is there any way to write Pair_Iterator so that the instantiation of interest passes?

Aucun commentaire:

Enregistrer un commentaire