c++ - MSVC std::pair 实现:SFINAE 是否在此处正确应用?

标签 c++ templates stl

考虑以下 std::pair 的代码Microsoft Visual Studio 15.4.5 附带的 STL 实现的默认构造函数:

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
    }

我设置了/std:c++latest选项,所以,根据标准(我在这里使用草案 n4659)我希望如果 _Ty1 中的任何一个,这个构造函数将被排除在重载决议之外。或 _Ty1不是默认可构造的:

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.]

在上面的实现中,排除是按如下方式执行的:

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

据我所知,SFINAE does not work用于模板类型参数的默认值。

有趣的是,在 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
    }

所以我想知道第一个实现是否正确,如果正确,将其更改为第二个有什么意义。

最佳答案

并不是说 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 构造函数模板,如果不知道其他构造函数模板是什么,您无法真正判断它是否正确。也就是说,如果他们弄错了,我会感到非常惊讶;任何问题都应该可以通过简单的单元测试轻松发现。

关于c++ - MSVC std::pair 实现:SFINAE 是否在此处正确应用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48233615/

相关文章:

c++ - 测试 std::bitset 中的位范围

c++ - 如何转换标准 :string to CString in unicode project

c++ - HOG 特征维度的大小

c++ - 使用一堆文件和 CUDA 浏览 C++ 项目的 Textmate

c++ - 你最喜欢的 Windbg 提示/技巧是什么?

c++ - 努力理解 C++ 模板实例化

c++ - 使用 C++ 和 STL 的 vector 元素乘积

c++ - 错误 C2100 - 非法间接

c++ - 警告 : narrowing conversion C++11

c++ - 在临时对象上调用方法