Reputation: 889
C++-14 introduced std::enable_if_t
.
What is the difference between it and std::enable_if
? Are there any advantages or differences in using std::enable_if_t
?
Upvotes: 9
Views: 4804
Reputation: 36399
The _t
aliases were introduced in c++14, the _v
ones were added in c++17.
Anywhere you use enable_if::type
you can use enable_if_t
(as long as your compiler and standard library support c++14) instead they are equivalent.
Upvotes: 4
Reputation: 73186
C++14 integrated all but part 4 of
written by well-renowned template metaprogramming guru Walter E. Brown✝.
What is the difference between it [
std::enable_if_t
] andstd::enable_if
? Are there any advantages or differences in usingstd::enable_if_t
?
The _t
alias templates for accessing the underlying type
of a metafunction, typename metafunction-name<metafunction-argument(s)>::type
, has not been added solely as syntactic sugar to language, but also to lessen the burden on inexperienced (Brown: "[...] inexpert") metaprogramming developers when facing compiler error messages whilst working with metafunctions. Quoting (the majority parts of) Section 2 (Proposal) of N3655 [emphasis mine]:
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
typename
keyword, 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 foradd_cv<T>::type
would beadd_cv_t<T>
.
Thus, generally, for brevity and a smaller risk for cryptic (lack of typename
-induced) compiler errors, as of C++14 always favour using the alias template (e.g. add_cv_t<T>
) over the more verbose form (e.g. typename add_cv<T>::type
).
[...] Are there any advantages or differences in using
std::enable_if_t
?
I.e., for your particular example, always favour using the alias template std::enable_if_t<T>
over the more verbose form typename enable_if<T>::type
.
Note that as of C++17,
has been adapted which, in short applies a similar pattern for traits with a single, static
member constant named value
, supplying a variable template helper suffixed _v
. Citing the summary/notes for P0006R0 from P0636R0 (Changes between C++14 and C++17 DIS)
For every standard type trait
foo
with a single, static member constantfoo<Args...>::value
, there is now a variable templatefoo_v<Args...>
.
(✝) For some excellent talks from Walter E. Brown on templates, see e.g.:
Upvotes: 2
Reputation: 185
std::enable_if_t
enables you to skip typename
and ::type
. So std::enable_if_t
is an alias of std::enable_if</* */>::type
.
So instead of typename std::enable_if</* */>::type
, you can write as std::enable_if_t</* */>
.
Upvotes: 2
Reputation: 2038
std::enable_if_t is a type alias of the inner ::type of std::enable_if, it's syntactic sugar so you don't have to write
typename std::enable_if</* */>::type
Upvotes: 9