Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this considered SFINAE?

Tags:

c++

c++11

sfinae

I asked a question about a week ago inquiring how I would be able to simply instantiate a class template only if the type it took had a specific member function. In my answer I got sort of a complicated solution. But then I tried to do it on my own. I just wanted to know if this enough to figure out of a given type T has a void function named f taking 0 parameters.

#include <type_traits>
#include <utility>

template <typename T, typename = void>
struct has_f : std::false_type { };

template <typename T>
struct has_f<
    T,
    decltype(std::declval<T>().f(), void())> : std::true_type { };

template <typename T, typename = typename std::enable_if<has_f<T>::value>::type>
struct A { };

struct B
{
    void f();
};

struct C { };

template class A<B>; // compiles
template class A<C>; // error: no type named ‘type’ 
                     // in ‘struct std::enable_if<false, void>’

If so, why are the other answers so complicated in this thread?

like image 810
Me myself and I Avatar asked Jun 15 '13 14:06

Me myself and I


People also ask

What is meant by SFINAE?

Substitution failure is not an error (SFINAE) refers to a situation in C++ where an invalid substitution of template parameters is not in itself an error. David Vandevoorde first introduced the acronym SFINAE to describe related programming techniques.

When to use SFINAE?

This rule applies during overload resolution of function templates: When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error. This feature is used in template metaprogramming.

What is Typename C++?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.


1 Answers

Yep, you have solved it in the simplest, most idiomatic style of C++11 SFINAE.

Note that you didn't check that the return type is void, that it's a nonstatic member, nor that there are no parameters. f is simply callable with no arguments. It could even be a functor.

To check for a nullary member nonstatic function returning void, use

template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) >( &T::f ) )) >
    : std::true_type {};

template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) const >( &T::f ) )) >
    : std::true_type {};
like image 52
Potatoswatter Avatar answered Oct 12 '22 04:10

Potatoswatter