Quick Q: How can I avoid writing ::value and ::type when using std::enable_if? -- StackOverflow

Quick A: Use a template alias. Several standard ones are coming in C++14.

Recently on SO:

How can I avoid writing ::value and ::type when using std::enable_if? [cppx]

In some of my code, namely the header rfc/cppx/text/String.h, I found the following mysterious snippet:

template< class S, class enable = CPPX_IF_( Is_a_< String, S > ) >
void operator!  ( S const& )
{ string_detail::Meaningless::operation(); }

The operator! is in support of a String class that has an implicit conversion to raw pointer. So I overload (among others) operator! for this class and derived classes, so that inadvertent use of a non-supported operator will give a suitable compilation error, mentioning that it's meaningless and inaccessible. Which I think is much preferable to such usage being silently accepted with an unexpected, incorrect result.

The CPPX_IF_ macro supports Visual C++ 12.0 (2013) and earlier, which finds C++11 using to be mostly beyond its ken. For a more standard-conforming compiler I would have written just ...

template< class S, class enable = If_< Is_a_< String, S > > >
void operator!  ( S const& )
{ string_detail::Meaningless::operation(); }

This looks like std::enable_if,

template< class S, class enabled = typename std::enable_if< Is_a_< String, S >::value, void >::type >
void operator!  ( S const& )
{ string_detail::Meaningless::operation(); }

except that the If_ or CPPX_IF_, and its expression, is much more concise and readable.

How on Earth did I do that?

 

Add a Comment

Comments are closed.

Comments (1)

0 0

Potatoswatter said on Jan 23, 2014 08:00 PM:

I don't believe the top answers are conforming per C++11 ยง14.8.2/8: "Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure." I posted this comment to each:

Danger Will Robinson! Substitution of an alias template isn't in the SFINAE context of a declaration. If your compiler doesn't complain when `::type` is absent, it probably should, and others will. `_t` does work nicely but not with SFINAE, at least as currently specified.