Alias ββtemplates, such as constraint , are replaced in any template definition in which they are used. They are special: other templates are replaced after providing certain arguments.
So this announcement:
template<typename T, constraint<Pointer<T>> = required> void foo();
roughly equivalent to this declaration (the difference is replacing a static_cast with an implicit conversion):
template<typename T, decltype(static_cast<constraint_success*> (require_t<std::is_pointer<T>>::result)) = required> void foo();
This creates SFINAE if static_cast not valid.
The effect is useful and essentially allows you to emulate limitations from the function of upcoming concepts. However, this particular approach is rather confusing, and you are not actually using it.
The canonical approach of SFINAE is as follows:
template< typename T > std::enable_if_t< std::is_pointer< T >::value > foo();
You can be a little cleaner and smarter and remove SFINAE from the return type - what you are going to do now:
template< typename T, std::enable_if_t< std::is_pointer< T >::value > * = nullptr > void foo();
Given the variable templates in the TS knowledge base, this corresponds to a symbol-symbol with your example:
template< typename T, std::enable_if_t< std::is_pointer_v< T > > * = nullptr > void foo();
The true Concepts-ish method is as follows:
template< typename T, std::enable_if_t< std::is_pointer< T >::value > * = nullptr > using Pointer = T; template< typename T > void foo( Pointer<T> );
Potatoswatter
source share