Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2005-01-02 13:00:03


On Jan 2, 2005, at 11:01 AM, John Maddock wrote:

>> This is a characteristic of pair, not make_pair. And it could be
>> disabled by restricting the member template constructor in:
>>
>> template <class T1, class T2>
>> struct pair {
>> typedef T1 first_type;
>> typedef T2 second_type;
>>
>> T1 first;
>> T2 second;
>> pair();
>> pair(const T1& x, const T2& y);
>> template<class U, class V> pair(const pair<U, V> &p);
>> };
>>
>> such that is_convertible<U, T1> and is_convertible<V, T2>, which is a
>> change I would support.
>
> If we do that, then we should do the same for the tuple constructors
> as well.

Absolutely. In fact, I'd really like to go a step or two further (for
C++0X, not tr1):

Introduce a trait:

template <class P1, class P2>
struct tuple_convertible
{
     static const bool value = ...
};

Such that value is true only if both P1 and P2 are "tuple like" (there
used to be trait for "tuple like"), and tuple_size<P1>::value ==
tuple_size<P2>::value, and for every element I in P1 and P2,
is_convertible<tuple_element<I,P1>::type, tuple_element<I,P2>::type>.
I.e. tuple_convertible answers true only if P1 and P2 are tuples of the
same size and each member of P1 is convertible to the corresponding
member of P2.

And then pair could look like:

template <class T1, class T2>
struct pair
{
     typedef T1 first_type;
     typedef T2 second_type;

     T1 first;
     T2 second;

     pair();
     pair(const T1& x, const T2& y); // needed only for binary
compatibility
     template <class U, class V> pair(U&& x, V&& y);

// pair(const pair& p); // implicitly generated
// pair& operator=(const pair& p); // implicitly generated
     pair(pair&& p);
     pair& operator=(pair&& p);

     template <class P>
         pair(P&& p, typename enable_if<tuple_convertible<P,
pair>::value>::type* = 0);
     template <class P>
         pair(const P& p, typename enable_if<tuple_convertible<P,
pair>::value>::type* = 0);

     template <class P> pair& operator=(P&& p);
     template <class P> pair& operator=(const P& p);

     void swap(pair&& p);
};

Here is a move-aware pair capable of holding move-only types, of moving
in heavy weight rvalues, of interoperability with all compatible
tuple-like types, including tuple, array, complex, and simply other
types of pair. is_convertible will answer correctly when asked about
pair and some other tuple-like type. And explicit constructors of T1
and T2 will be respected as Pavel requests.

And yes, I'd like to see at least tuple and complex outfitted
similarly. array is a special case that may not be able to do this,
unless we can start adding ctors to it via another core extension.

Btw, I kind of like "decayed" for a name.

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk