Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excluding std::pair constructors that use explicit construction

Tags:

c++

c++11

sfinae

Following on from this answer, it seems these constructors:

template<class U, class V> pair(pair<U, V>&& p); 
template<class U, class V> pair(const pair<U, V>& p);

are forbidden from participating in overload resolution when they would require an explicit conversion.

From C++11 (§20.3.2, n3290):

Remark: This constructor shall not participate in overload resolution unless U is implicitly convertible to first_type and V is implicitly convertible to second_type.

An interesting SFINAE workaround has been suggested, but this digresses from the text of the standard.

How can a conforming implementation possibly exclude this from overload resolution, short of some special internal compiler magic? I.e. can an implementation do this and can I duplicate it for my own type perhaps? There doesn't seem to be anyway of conforming with this! Is it a hangover from the removal of concepts from C++11?

I did wonder about using a private constructor to do the SFINAE part and delegating from the public constructor, but it doesn't look like constructor delegation participates in SFINAE in such a way as to make that work.

like image 566
Flexo Avatar asked Nov 15 '11 14:11

Flexo


2 Answers

but this digresses from the text of the standard

An implementation is allowed to add default arguments to any non-virtual library member function. This seems to permit precisely this kind of SFINAE tricks.

like image 68
n. 1.8e9-where's-my-share m. Avatar answered Sep 22 '22 22:09

n. 1.8e9-where's-my-share m.


I was missing two pieces of information:

  1. gcc uses this:

    template<class _U1, class _U2, class = typename
                   std::enable_if<std::is_convertible<_U1, _T1>::value
                                  && std::is_convertible<_U2, _T2>::value>::type>
            pair(_U1&& __x, _U2&& __y)
            : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
    

    The trick seems to be in the default for the anonymous class template parameter. I'd not seen that before and this implementation didn't use that.

  2. I missed that gcc actually implemented this.
like image 45
Flexo Avatar answered Sep 24 '22 22:09

Flexo