Yet Another SFINAE tool in C++11

SFINAE in C++03 typically uses the {cpp}sizeof{/cpp} operator to determine which overload for a function was valid, and hence whether the type under consideration has a particular property, usually a {cpp}typedef{/cpp}. Here is the prototypical C++03 code for finding if a type {cpp}T{/cpp} has a {cpp}typedef foo{/cpp} inside it.
[cpp]
template
struct has_typedef_foo {
typedef struct {} yes;
typedef yes no[2];

template
static yes& test(typename C::foo*);

template
static no& test(…);

static const bool value = (sizeof(test(0)) == sizeof(yes));
};
[/cpp]

With C++11, we can use another unevaluated context, namely {cpp}decltype{/cpp} to check for the return type of the function that was valid. The {cpp}value{/cpp} variable can now be
[cpp]
static const bool value = std::is_same(0)), yes&>::value;
[/cpp]
There is yet another unevaluated context in C++11, namely the {cpp}noexcept{/cpp} operator. The operator is passed an expression, and it returns {cpp}true{/cpp} or {cpp}false{/cpp} depending on whether the expression is expected NOT to throw an exception or IS expected to throw an exception, respectively. We can make use of that fact, and define the two versions of the {cpp}test{/cpp} function to throw and not throw. Here is a version that uses the {cpp}noexcept{/cpp} operator, and doesn’t have the helper {cpp}yes/no{/cpp} types.
[cpp]
template
struct has_typedef_foo {
template
static void test(typename C::foo*) noexcept;

template
static void test(…) noexcept(false);

static const bool value = noexcept(test(0));
};
[/cpp]

0 Responses to “Yet Another SFINAE tool in C++11”


  • No Comments

Leave a Reply

*