【问题标题】:What is the difference between std::enable_if and std::enable_if_t?std::enable_if 和 std::enable_if_t 有什么区别?
【发布时间】:2020-09-30 19:36:58
【问题描述】:

C++-14 引入了 std::enable_if_t。

它和std::enable_if有什么区别?使用 std::enable_if_t 有什么优势或区别吗?

【问题讨论】:

    标签: c++ templates stl


    【解决方案1】:

    std::enable_if_t 是 std::enable_if 的内部 ::type 的类型别名,它是语法糖,所以你不必写

    typename std::enable_if</* */>::type
    

    【讨论】:

      【解决方案2】:

      std::enable_if_t 使您可以跳过typename::type。所以std::enable_if_tstd::enable_if&lt;/* */&gt;::type 的别名。

      所以你可以写成std::enable_if_t&lt;/* */&gt;,而不是类型名std::enable_if&lt;/* */&gt;::type

      【讨论】:

        【解决方案3】:

        _t 别名是在 c++14 中引入的,_v 是在 c++17 中添加的。

        在您使用enable_if::type 的任何地方,您都可以使用enable_if_t(只要您的编译器和标准库支持c++14),它们是等价的。

        【讨论】:

        • 请注意,虽然特征的别名模板是在 C++14 中引入的,但 特征的变量模板 仅在 C++17 中添加,即使变量模板本身也是如此已经在 C++14 中可用(有关详细信息,请参阅 my answer)。
        【解决方案4】:

        C++14 (N3655):特征的别名模板

        C++14 集成了除第 4 部分之外的所有内容

        由著名的模板元编程大师Walter E. Brown编写。

        它[std::enable_if_t]和std::enable_if有什么区别?使用std::enable_if_t有什么优势或者区别吗?

        _t 别名模板用于访问元函数 typename metafunction-name&lt;metafunction-argument(s)&gt;::type 的底层 type并未仅作为语法糖添加到语言中,同时也是为了减轻没有经验的人的负担(布朗:“[...] inexpert”)元编程开发人员在使用元函数时遇到编译器错误消息。引用 N3655 [emphasis mine] 第 2 节(提案)的(大部分):

        不幸的是,上述灵活性伴随着成本 最常见的用例。在模板上下文中,C++ 要求 对元函数的每个“元调用”都以形式承担语法开销 一个介绍性的typenamekeyword,以及后缀 ::type:

        typename metafunction-name<metafunction-argument(s)>::type
        

        即使是相对简单的作品也可以很快变成 有点凌乱;更深的嵌套非常笨拙:

        template< class T > using reference_t
          = typename conditional<is_reference<T>::value, T,
                                 typename add_lvalue_reference<T>::type>::type;
        

        更糟糕的是,不小心省略了关键字可能会导致诊断 对不擅长元编程的程序员来说是神秘的 详情。

        [...] 因此,我们建议为 库的TransformationTraits 为了减少程序员 负担 [...]。请注意,在上述示例的以下重写中, 没有任何typename 关键字,以及没有任何::type 后缀,因此将声明从 3 压缩到 2 代码行数:

        template< class T > using reference_t 
          = conditional_t< is_reference<T>::value, T, add_lvalue_reference_t<T> >;
        

        [...] 我们建议根据一致的命名别名 模式,即_t为后缀的别名特征的名称, 表示类型别名的常规后缀。因此,例如, add_cv&lt;T&gt;::type 的别名是 add_cv_t&lt;T&gt;

        喜欢为特征使用别名模板

        因此,一般来说,为了简洁和更小的隐蔽(缺少typename-引发)编译器错误的风险,从 C++14 开始,总是倾向于使用别名模板(例如 add_cv_t&lt;T&gt;)而不是更详细的形式(例如typename add_cv&lt;T&gt;::type)。

        [...] 使用std::enable_if_t 有什么优势或区别吗?

        即,对于您的特定示例,始终倾向于使用别名模板 std::enable_if_t&lt;T&gt;,而不是更详细的形式 typename enable_if&lt;T&gt;::type


        C++17 (P0006R0):特征的变量模板

        请注意,从 C++17 开始,

        已被改编,简而言之,它对具有单个 static 成员常量 value 的特征应用了类似的模式,提供了一个后缀为 _v 的变量模板助手。引用 P0636R0 中 P0006R0 的摘要/注释(C++14 和 C++17 DIS 之间的变化

        对于每个具有单个静态成员常量 foo&lt;Args...&gt;::value 的标准类型特征 foo,现在有一个变量模板 foo_v&lt;Args...&gt;


        (✝) 有关 Walter E. Brown 关于模板的精彩演讲,请参阅例如:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-22
          • 2023-04-09
          • 2020-10-16
          • 2021-10-16
          • 2015-07-18
          • 2019-02-26
          • 2013-02-07
          相关资源
          最近更新 更多