Home MSVC std::pair implementation: is SFINAE applied correctly here?
Reply: 3

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

Edgar Rokyan
1#
Edgar Rokyan Published in 2018-01-12 20:32:08Z

Consider the following code of std::pair default constructor from the STL implementation shipped 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 /std:c++latest option, so, according to the standard (I use the draft n4659 here) I expect that this constructor will be excluded from the overload resolution if either _Ty1 or _Ty1 is not default constructible:

23.4.2 Class template pair [pairs.pair]

EXPLICIT constexpr pair();

Effects: Value-initializes first and second.

Remarks: This constructor shall not participate in overload resolution unless is_default_constructible_v<first_type> is true and is_default_constructible_v<second_type> is true. [ Note: This behavior can be implemented by a constructor template with default template arguments.]

In the implementation above the exclusion is performed as follows:

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

As far as I know, SFINAE does not work for template type parameters default values.

Interestingly enough, in Microsoft Visual Studio 15.5.3 the constructor has been changed to the "right version" ("right" based on my limited template knowledge):

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
    }

So I am wondering whether the first implementation is correct, and, if it is correct, what is the point of changing it to the second one.

T.C.
2#
T.C. Reply to 2018-01-12 20:45:48Z

It's not that SFINAE doesn't work inside default template arguments; it's that they do not count as part of the signature and so putting your SFINAE machinery there means that you have to make the signature different in some other way if you want to build an overload set.

Thus, this is fine:

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();

because the signatures are different (return type is part of the signature of function templates - but not functions); so is this:

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&);

but this isn't (it redeclares the same function template and so tries to give the same template parameter a default template argument twice):

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&);

With respect to that pair constructor template in particular, you can't really tell if it's correct without knowing what the other constructor templates are. That said, I'd be greatly surprised if they got it wrong; any problem should be easily catchable with simple unit tests.

Timur Kukharskiy
3#
Timur Kukharskiy Reply to 2018-01-12 20:53:28Z

I think they are both right , but second more flexible.

SergeyA
4#
SergeyA Reply to 2018-01-12 21:04:21Z

I believe it is correct, because the point of SFINAE usage there is to make sure constructor is only available when elements are default-constructible, and not to allow selection of different overloads of said constructor.

By definition, there is only one version of constructor (or any other function for that matter) which accepts 0 arguments, so overload resolution is not a problem here.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.307439 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO