std::enable_if和std::enable_if_t的区别是什么?

6

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

它与std :: enable_if之间有什么区别?使用std :: enable_if_t是否有任何优势或差异?

4个回答

7

std::enable_if_t是std::enable_if的内部::type别名,它是一种语法糖,使您不必编写

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

3

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

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


请注意,尽管C++14引入了特征的别名模板,但是C++17中才添加了用于特征的变量模板,即使变量模板本身在C++14中已经可用(有关详细信息,请参见我的答案)。 - dfrib

2

std::enable_if_t 可以让你省略 typename::type。因此,std::enable_if_tstd::enable_if</* */>::type 的别名。

所以,你可以将 typename std::enable_if</* */>::type 写成 std::enable_if_t</* */>


2

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

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

std::enable_if_tstd::enable_if有什么区别?在使用std::enable_if_t时有什么优势或区别吗?

_t别名模板用于访问元函数的底层type,即typename metafunction-name<metafunction-argument(s)>::type。这不仅仅是为了语法上的简化,而且也是为了减轻经验不足的元编程开发人员在使用元函数时面对编译器错误消息的负担。引用N3655的第2节(提案)的大部分内容,强调如下:

Unfortunately, the above-described flexibility comes with a cost for the most common use cases. In a template context, C++ requires that each “metacall” to a metafunction bear syntactic overhead in the form of an introductory typenamekeyword, as well as the suffixed ::type:

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

Even relatively straightforward compositions can rather quickly become somewhat messy; deeper nesting is downright unwieldy:

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

Worse, accidentally omitting the keyword can lead to diagnostics that are arcane to programmers who are inexpert in metaprogramming details.

[...] We therefore propose to add a set of template aliases for the library’s TransformationTraits in order to reduce the programmer burden [...]. Note, in the following rewrite of the above example, the absence of any typename keyword, as well as the absence of any ::type suffix, thus condensing the statement from 3 to 2 lines of code:

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

[...] we recommend that aliases be named according to a consistent pattern, namely the name of the aliased trait suffixed by _t, the conventional suffix denoting a type alias. Thus, for example, the alias for add_cv<T>::type would be add_cv_t<T>.

更倾向于使用别名模板来定义特性

因此,通常情况下,为了简洁和减少编译器错误的风险(由于缺乏typename),从C++14开始,始终更倾向于使用别名模板(例如add_cv_t<T>)而不是更冗长的形式(例如typename add_cv<T>::type)。

[...] 使用std::enable_if_t有哪些优势或差异?

也就是说,在你的特定例子中,始终更倾向于使用别名模板std::enable_if_t<T>而不是更冗长的形式typename enable_if<T>::type


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

需要注意的是,从C++17开始,

已经被采用,简而言之,这适用于具有单个static成员常量value的特征,提供了一个以_v结尾的变量模板助手。引用来自P0636R0C++14和C++17 DIS之间的更改)的P0006R0的摘要/注释如下:

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


(✝) 如果想听 Walter E. Brown 关于模板的优秀演讲,请参见以下链接:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接