可变模板专业化问题

uni*_*ptr 1 c++ templates variadic-templates c++11

我想要一个通用的方法来处理函数并最终调用它们所以我编写下面的代码问题是代码正在编译但是当我测试它时我得到了类的错误

错误的模板参数数量(1,应为0)auto al = action :: apply <5> :: value;

所以我知道我做错了什么,但我找不到它是什么.

template<typename T, typename enabled=void, typename ...P>
struct action{
    template<P... args>
    struct apply{ };
};

template<typename FN,typename ...P>
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...>{
    template<P... args>
    struct apply{ 
         static const  decltype( std::result_of<FN(P...)>::type ) value = FN( std::forward<P>(args)...);
    };
};


int test(int x)
{
    return x;
}

int main()
{
  auto al= action<decltype(test), int>::apply<5>::value;
  std::cout << "result :" << al <<std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 8

这是您的主要模板:

template<typename T, typename enabled=void, typename ...P>
struct action
Run Code Online (Sandbox Code Playgroud)

无论何时action<blah>,都通过此主模板解释参数.

action<decltype(test), int>
Run Code Online (Sandbox Code Playgroud)

所以在这里,你传递decltype(test)as Tintas enabled.没什么...P.

然后,我们测试是否适用任何模板专业化.

template<typename FN,typename ...P>
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...>
Run Code Online (Sandbox Code Playgroud)

这需要分解.该部分 action是对我们的模式匹配.之前的部分只是我们从中推导出的一些变量.

所以

action<decltype(test), int>
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...>
Run Code Online (Sandbox Code Playgroud)

排队:

       action<decltype(test), int>
struct action<FN            , typename std::enable_if< std::is_function<FN>::value >::type ,P...>
Run Code Online (Sandbox Code Playgroud)

以下是它们的对应方式:

FN=decltype(test)
typename std::enable_if< std::is_function<FN>::value >::type=int
P...=
Run Code Online (Sandbox Code Playgroud)

好吧,所以争论1是decltype(test),又名int(int).我们推断这是FN.都好.

接下来,有两个参数.所以...P显然是空的.

参数2处于非推导的上下文中.我们计算出来了:

typename std::enable_if< std::is_function<FN>::value >::type
typename std::enable_if< std::is_function<int(int)>::value >::type
typename std::enable_if< true >::type
void
Run Code Online (Sandbox Code Playgroud)

......好吧,这个专业化说它是void.但我们过去了int.由于void=int无意义,此专业化不适用.我们在这里没有模式匹配.

因此我们回到主要专业化:

template<typename T, typename enabled=void, typename ...P>
struct action{
  template<P... args>
  struct apply{ };
};
Run Code Online (Sandbox Code Playgroud)

好吧,所以它有一个成员模板apply,只需要0个非类型参数,因为它...P是空的.

因此你的错误.

专业化不是重载.它们是主模板的模式匹配实现替换.主模板参数始终是签名.专业化可以重命名和模式匹配某些选择.

您可能想要使用别名.重命名actionaction_helper.可选择将其放在details命名空间中.然后:

template<class T, class...P>
using action = action_helper<T,void,P...>;
Run Code Online (Sandbox Code Playgroud)

action在客户端代码中使用.