MSVC std :: pair implementation: is SFINAE applied correctly here?

Consider the following default default constructor code std::pairfrom the STL implementation that ships with Microsoft Visual Studio 15.4.5:

template<class _Uty1 = _Ty1,
    class _Uty2 = _Ty2,
    class = enable_if_t<is_default_constructible<_Uty1>::value
                    && is_default_constructible<_Uty2>::value>>
    constexpr pair()
    : first(), second()
    {   // default construct
    }

I set the parameter /std:c++latest, so according to the standard (I am using the n4659 project here), I expect this constructor to be excluded from overload resolution if either _Ty1or is _Ty1not constructive by default:

23.4.2 Pair of pattern template [par.]

EXPLICIT constexpr pair ();

Effects: the value initializes the first and second.

: is_default_constructible_v<first_type> is_default_constructible_v<second_type> . [: .]

:

class = enable_if_t<is_default_constructible<_Uty1>::value
                    && is_default_constructible<_Uty2>::value>

, SFINAE .

, Microsoft Visual Studio 15.5.3 " " ( "" ):

template<class _Uty1 = _Ty1,
    class _Uty2 = _Ty2,
    enable_if_t<conjunction_v<
        is_default_constructible<_Uty1>,
        is_default_constructible<_Uty2>
    >, int> = 0>
    constexpr pair()
    : first(), second()
    {   // default construct
    }

, , , , , .

+4
3

, SFINAE ; , , SFINAE , -, .

, :

template<class T, class=std::enable_if_t<std::is_integral_v<T>>>
T meow();

template<class T, class=std::enable_if_t<!std::is_integral_v<T>>>
void meow();

( , ); :

template<class T, class=std::enable_if_t<std::is_integral_v<T>>>
void meow(T);

template<class T, class=std::enable_if_t<!std::is_integral_v<T>>>
void meow(const T&);

( ):

template<class T, class=std::enable_if_t<std::is_integral_v<T>>>
void meow(const T&);

template<class T, class=std::enable_if_t<!std::is_integral_v<T>>>
void meow(const T&);

pair, , , , , . , , ; .

+6

, , .

0

I believe that this is correct, because the point of using SFINAE is to make sure that the constructor is only available when the default elements are constructive and do not allow you to select different overloads of the specified constructor.

By definition, there is only one version of the constructor (or any other function in this regard) that takes 0 arguments, so overload resolution is not a problem here.

0
source

Source: https://habr.com/ru/post/1692116/


All Articles