C ++ 11 - 模板std :: enable_if和std :: result_of

时间:2016-10-17 08:56:41

标签: c++ c++11 templates

我创建了这个来专门化void / non-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()
{
   //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>();

(基于这个答案:C++ template parameter as function call name

Hovewer,这给了我一堆错误(MSVC 2015)。如果我在

中运行
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;
}

我得到true结果。

是否可以&#34;创建&#34;具有MethodName

的无效/非空结果的专门化功能

2 个答案:

答案 0 :(得分:2)

这在GCC下编译好

#include <iostream>
#include <type_traits>
using namespace std;

template <typename ClassType, typename MethodType, MethodType MethodName>
static auto function()
  -> std::enable_if_t<std::is_void<typename std::result_of<MethodType(ClassType)>::type>::value, int>
{
   //void
   //....
}

template <typename ClassType,  typename MethodType, MethodType MethodName>
static auto function()
  -> std::enable_if_t<!std::is_void<typename std::result_of<MethodType(ClassType)>::type>::value, int>
{
   //non-void
   //....
}

我不确定这是否是你正在寻找的东西,但我使用箭头语法将enable_if移动到返回类型,这看起来对我来说更干净。另外,为什么在MethodName上使用decltype,因为你已经有类型为MethodType。在访问类型之前,result_of还需要typename。

如上所述,虽然没有可能的用法,但我不确定这是否是你所追求的。

注意:如果您不能将此更改用于std::enable_if_t,则{C} 14中可以使用typename std::enable_if<...>::type

答案 1 :(得分:1)

您错过了typename

作为替代方案,我建议:

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>{}();
}

使用

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

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

使用C ++ 17,我们可以用template <auto f> struct function_helper;

删除第一个模板参数