This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

template constructor overload problems


I've sent this question to comp.std.c++ earlier this week but the message hasn't appeared yet.

I'm sending it to this list because it pertains to problems with the current <tuple> implementation.

Consider this code.

template <typename Element>
struct tuple {

tuple () { }

  template <typename UElements>
  explicit
  tuple (UElements&& elements)
  { static_assert(!sizeof(UElements), "first constructor"); }

  template <typename UElements>
  tuple (tuple<UElements>&& foo)
  { static_assert(!sizeof(UElements), "second constructor"); }

};

int
main (int argc, char* argv[]) {

  tuple<int> f1;
  tuple<unsigned> f2(f1);

  return 0;
}

mainline currently gives me this error:

../src/main.cpp: In constructor âtuple<Element>::tuple(UElements&&) [with UElements = tuple<int>&, Element = unsigned int]â:
../src/main.cpp:21: instantiated from here
../src/main.cpp:9: error: static assertion failed: "first constructor"


If I take the first constructor out, I get "second constructor" in the error, so both constructors are actually entering the overload set.

Is this behaviour correct?

This code is beyond my knowledge of overload resolution.

I have a patch for <tuple> that fails four test cases with similar errors. Example:

/home/pedro.lamarao/Projetos/gcc/mainline-obj/i686-pc-linux-gnu/libstdc++-v3/include/tuple: In constructor 'std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = std::tuple<const int&>&, int _Idx = 0, _Head = const int&]':
/home/pedro.lamarao/Projetos/gcc/mainline-obj/i686-pc-linux-gnu/libstdc++-v3/include/tuple:155: instantiated from 'std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(_UHead&&, _UTail&& ...) [with _UHead = std::tuple<const int&>&, _UTail = , int _Idx = 0, _Head = const int&, _Tail = ]'
/home/pedro.lamarao/Projetos/gcc/mainline-obj/i686-pc-linux-gnu/libstdc++-v3/include/tuple:224: instantiated from 'std::tuple<_Elements>::tuple(_UElements&& ...) [with _UElements = std::tuple<const int&>&, _Elements = const int&]'
/home/pedro.lamarao/Projetos/gcc/mainline/libstdc++-v3/testsuite/20_util/tuple/cons/constructor.cc:50: instantiated from here
/home/pedro.lamarao/Projetos/gcc/mainline-obj/i686-pc-linux-gnu/libstdc++-v3/include/tuple:97: error: invalid initialization of reference of type 'const int&' from expression of type 'std::tuple<const int&>'


That is, when a tuple is initialized with a lvalue of tuple type, the compiler is picking this constructor:

      template<typename... _UElements>
        explicit
        tuple(_UElements&&... __elements)

instead of this one:

      template<typename... _UElements>
        tuple(const tuple<_UElements...>& __in)

and eventually the implementation will try to assign the tuple object to (say) an int object.

Initially I thought this should be solved with enable_if to match argument pack sizes; but even if I had succeded in implementing this (I wasn't) there is the corner case of tuples with only one element.

Am I missing something?

If the compiler is picking the correct constructor, isn't this a design error in the tuple specification? Or should there be tricks in place to constrain the template constructors?

--
 P.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]