tersrth
tersrth

Reputation: 889

What is the difference between std::enable_if and 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?

Upvotes: 9

Views: 4804

Answers (4)

Alan Birtles
Alan Birtles

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

dfrib
dfrib

Reputation: 73186

C++14 (N3655): Alias Templates for Traits

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] and std::enable_if? Are there any advantages or differences in using std::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)>::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>.

Favour using the alias templates for traits

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.


C++17 (P0006R0): Variable Templates for Traits

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 constant foo<Args...>::value, there is now a variable template foo_v<Args...>.


(✝) For some excellent talks from Walter E. Brown on templates, see e.g.:

Upvotes: 2

Owl66
Owl66

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

Yamahari
Yamahari

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

Related Questions