Why 'is_convertible' here in <utility> std::pair (STL)?

Viewed 292
    template<class _Other1,
    class _Other2,
    class = enable_if_t<is_constructible<_Ty1, _Other1>::value
                    && is_constructible<_Ty2, _Other2>::value>,
    enable_if_t<is_convertible<_Other1, _Ty1>::value
            && is_convertible<_Other2, _Ty2>::value, int> = 0>
    constexpr pair(pair<_Other1, _Other2>&& _Right)
        _NOEXCEPT_OP((is_nothrow_constructible<_Ty1, _Other1>::value
            && is_nothrow_constructible<_Ty2, _Other2>::value))
    : first(_STD forward<_Other1>(_Right.first)),
        second(_STD forward<_Other2>(_Right.second))
    {   // construct from moved compatible pair
    }

template<class _Other1,
    class _Other2,
    class = enable_if_t<is_constructible<_Ty1, _Other1>::value
                    && is_constructible<_Ty2, _Other2>::value>,
    enable_if_t<!is_convertible<_Other1, _Ty1>::value
            || !is_convertible<_Other2, _Ty2>::value, int> = 0>
    constexpr explicit pair(pair<_Other1, _Other2>&& _Right)
        _NOEXCEPT_OP((is_nothrow_constructible<_Ty1, _Other1>::value
            && is_nothrow_constructible<_Ty2, _Other2>::value))
    : first(_STD forward<_Other1>(_Right.first)),
        second(_STD forward<_Other2>(_Right.second))
    {   // construct from moved compatible pair
    }

utility file for VS 2017 line 206, _Other1 and _Other2 are parameters, this is std::pair's construction func, and we are using Other1 and Other2 to initialize "first" and "second",

I think is_constructible is enough, why are we using is_convertible here?
and by the way, what's the difference between class = enable_if_t< ... ::value> and enable_if_t< ... ::value,int> = 0?

2 Answers
Related