This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
template constructor overload problems
- From: Pedro LamarÃo <pedro dot lamarao at mndfck dot org>
- To: libstdc++ at gcc dot gnu dot org
- Date: Fri, 15 Feb 2008 21:01:10 -0200
- Subject: 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.