[c++0x] Problem with std::tuple's template converting constructors

0 views
Skip to first unread message

Pedro Lamarão

unread,
Feb 19, 2008, 5:45:39 PM2/19/08
to
The first version of this message went to comp.std.c++ but I've just
learned it is down.

The following issue was discussed in the libstdc++ development list
with Peter Dimov and Paolo Carlini while discussing the initialization
of tuple objects with "move-only" types.

Consider the following 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); // A

return 0;
}

Line A above will always fails with the message "second constructor".
The overload set for constructing f2 is deduced as:

tuple( tuple<int>& elements ); // first constructor
tuple( tuple<int>&& foo ); // second constructor

with the first constructor a better match for the lvalue f1.
The obvious intent is for tuple objects to select the second
constructor.

The proposed solution was to introduce a third constructor to better
match lvalue tuples.

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

Is this solution complete?

--
P.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Howard Hinnant

unread,
Feb 20, 2008, 12:44:33 AM2/20/08
to
In article
<5ad43c19-727b-42e1...@72g2000hsu.googlegroups.com>,
"Pedro Lamarão" <pedro....@gmail.com> wrote:

It fails if:

const tuple<int> f1;

which now binds back to "first constructor".

What we really need to do is constrain:

template <typename ...UElements>
explicit
tuple (UElements&&... elements)

such that tuple is constructible with UElements... . Currently the best
option for that is using concepts and std::Constructible (not yet in the
WP).

Failing that, the following is looking like a decent strategy to me:

template <typename ...Types>
struct tuple {

tuple () { }

explicit tuple(Types...)
{ static_assert(!sizeof(Types), "first constructor"); }

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

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

The implementation would move from the by value arguments in first
constructor.

-Howard

Reply all
Reply to author
Forward
0 new messages