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?
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?
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
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</* */>.
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.
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
typenamekeyword, as well as the suffixed::type:typename metafunction-name<metafunction-argument(s)>::typeEven 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
typenamekeyword, as well as the absence of any::typesuffix, 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>::typewould 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
foowith 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.: