Martin Perry Martin Perry - 1 month ago 14
C++ Question

C++11 - template std::enable_if and std::result_of

I have created this to specialize template for void / non-void methods

template <typename ClassType,
typename MethodType, MethodType MethodName,
typename std::enable_if <std::is_same<void, std::result_of<decltype(MethodName)(ClassType)>::type>::value> ::type* = nullptr
>
static int function()
{
//void
//....
}



template <typename ClassType,
typename MethodType, MethodType MethodName,
typename std::enable_if <!std::is_same<void, std::result_of<decltype(MethodName)(ClassType)>::type>::value> ::type* = nullptr
>
static int function()
{
//non-void
//....
}

//And I want to call it like this
function<Foo, void (Foo::*)(void), &Foo::Print>();
function<Foo, int (Foo::*)(void), &Foo::Print2>();


(Based on this answer: C++ template parameter as function call name)

Hovewer, this gives me bunch of errors (MSVC 2015). If I run this inside of

template <typename ClassType,
typename MethodType, MethodType MethodName
>
static int print()
{
std::cout << "C: " << std::is_same<void, std::result_of<decltype(MethodName)(ClassType)>::type>::value << std::endl;
}


I got
true
result.

Is it possible to "create" function with specialisation for void / non-void results of
MethodName
?

Answer

You have just miss typename.

As alternative I suggest:

template <typename F, F f> struct function_helper;

template <typename C, typename ... Ts, void (C::*m)(Ts...)>
struct function_helper<void (C::*)(Ts...), m>
{
    int operator()() const { /* void implementation*/ }
};

template <typename C, typename Ret, typename ... Ts, void (C::*m)(Ts...)>
struct function_helper<Ret (C::*)(Ts...), m>
{
    int operator()() const { /* non-void implementation*/ }
};

template <typename F, F f>
static int function()
{
     return function_helper<F, f>{}();
}

With usage

function<void (Foo::*)(), &Foo::Print>();
function<int (Foo::*)(), &Foo::Print2>();

or

function<decltype(&Foo::Print), &Foo::Print>();
function<decltype(&Foo::Print2), &Foo::Print2>();

With C++17, we may get rid of first template argument with template <auto f> struct function_helper;

Comments