C++ 多个typename的部分模板专门化 在下面的代码中,我想考虑函数( OP>代码> s),它具有无效>代码>返回,而被认为是返回真< /代码>。类型Retval,以及Op的返回值始终匹配。我无法使用此处显示的类型特征进行区分,尝试基于Retval创建部分模板专门化失败,因为存在其他模板变量Op和Args

C++ 多个typename的部分模板专门化 在下面的代码中,我想考虑函数( OP>代码> s),它具有无效>代码>返回,而被认为是返回真< /代码>。类型Retval,以及Op的返回值始终匹配。我无法使用此处显示的类型特征进行区分,尝试基于Retval创建部分模板专门化失败,因为存在其他模板变量Op和Args,c++,templates,c++11,return-type,template-specialization,C++,Templates,C++11,Return Type,Template Specialization,如何在模板专门化中只专门化一些变量而不出错?是否有其他方法根据Op的返回类型改变行为 template <typename Retval, typename Op, typename... Args> Retval single_op_wrapper( Retval const failval, char const *const opname, Op const op, Cpfs &cpfs,

如何在模板专门化中只专门化一些变量而不出错?是否有其他方法根据
Op
的返回类型改变行为

template <typename Retval, typename Op, typename... Args>
Retval single_op_wrapper(
        Retval const failval,
        char const *const opname,
        Op const op,
        Cpfs &cpfs,
        Args... args) {
    try {
        CallContext callctx(cpfs, opname);
        Retval retval;
        if (std::is_same<bool, Retval>::value) {
            (callctx.*op)(args...);
            retval = true;
        } else {
            retval = (callctx.*op)(args...);
        }
        assert(retval != failval);
        callctx.commit(cpfs);
        return retval;
    } catch (CpfsError const &exc) {
        cpfs_errno_set(exc.fserrno);
        LOGF(Info, "Failed with %s", cpfs_errno_str(exc.fserrno));
    }
    return failval;
}
模板
回收单包装纸(
返回常数failval,
char const*const opname,
警员警员警员,
CPF和CPF,
Args…Args){
试一试{
CallContext callctx(cpfs,opname);
复述复述;
if(std::is_same::value){
(callctx.*op)(args…);
retval=true;
}否则{
retval=(callctx.*op)(args…);
}
断言(retval!=failval);
callctx.commit(cpfs);
返回返回;
}捕获(CpfsError const&exc){
cpfs_errno_集合(exc.fserrno);
日志(信息,“与%s一起失败”,cpfs_errno_str(exc.fserrno));
}
返回failval;
}

您需要明确的专业化,而不是局部专业化

template <typename Retval, typename Op, typename... Args>
Retval single_op_wrapper(
        Retval const failval,
        char const *const opname,
        Op const op,
        Cpfs &cpfs,
        Args... args) {
    try {
        CallContext callctx(cpfs, opname);
        Retval retval;
        if (std::is_same<bool, Retval>::value) {
            (callctx.*op)(args...);
            retval = true;
        } else {
            retval = (callctx.*op)(args...);
        }
        assert(retval != failval);
        callctx.commit(cpfs);
        return retval;
    } catch (CpfsError const &exc) {
        cpfs_errno_set(exc.fserrno);
        LOGF(Info, "Failed with %s", cpfs_errno_str(exc.fserrno));
    }
    return failval;
}
template<typename Op, typename... Args> void single_op_wrapper<void, Op, Args>(...) {
    ...
}
模板
回收单包装纸(
返回常数failval,
char const*const opname,
警员警员警员,
CPF和CPF,
Args…Args){
试一试{
CallContext callctx(cpfs,opname);
复述复述;
if(std::is_same::value){
(callctx.*op)(args…);
retval=true;
}否则{
retval=(callctx.*op)(args…);
}
断言(retval!=failval);
callctx.commit(cpfs);
返回返回;
}捕获(CpfsError const&exc){
cpfs_errno_集合(exc.fserrno);
日志(信息,“与%s一起失败”,cpfs_errno_str(exc.fserrno));
}
返回failval;
}
模板无效单_op_包装(…){
...
}

编辑:忘记编写的是函数而不是类。

模板函数不能部分专用化。您可以做不同的事情:您可以使用单个静态方法将函数包装到类模板中,并专门化类模板,或者您可以使用SFINAE在不同的模板函数中选择函数的最佳选择:

template <typename O, typename Args...>
void single_op_wrapper( /* all but failval */ ) { // [+]
   // implementation for void
}
template <typename R, typename O, typename Args...>
typename boost::enable_if< boost::is_same<R,bool>, bool >::type // bool if condition is met
single_op_wrapper( /* all args */ ) {
   // implementation for R being a bool
}
template <typename R, typename O, typename Args...>
typename boost::enable_if< boost::is_same<R,char> >::type // by default bool
single_op_wrapper( /* all args */ ) {
   // implementation for void return
} 
template <typename R, typename O, typename Args...>
typename boost::disable_if_c<    boost::is_same<R,char>::value //[*] 
                              || boost::is_same<R,bool>::value
                              , R >::type
single_op_wrapper( /* all args */ ) {
   // implementation when R is neither bool nor void
}
模板
void single_op_包装(/*除failval*/)之外的所有内容{/[+]
//无效执行
}
模板
typename boost::如果::如果满足条件,则键入//bool
单个包装器(/*所有参数*/){
//R是bool的实现
}
模板
如果::type//默认为bool,则启用
单个包装器(/*所有参数*/){
//无效返还的实现
} 
模板
typename boost::如果\u c::类型
单个包装器(/*所有参数*/){
//当R既不是bool也不是void时的实现
}
在void[+]的单独模板上:

在C++中,您不能拥有一个函数,该函数接受类型<代码>无效>代码>的参数。这意味着您不能对
void
案例使用与其他案例相同的参数

在元编程方面:

这里有几个棘手的问题。。。
enable\u if
是一个元函数,它定义了一个内部类型(如果满足条件或没有其他条件)。当编译器尝试替换模板中的类型时,返回类型只有在满足条件时才有效(因此函数是候选函数)。
disable\u if
元函数具有相反的行为。直接变量
enable\u if
/
disable\u if
将一个元函数作为第一个参数,也可以选择一个类型作为第二个参数。第二个版本
enable\u if\u c
/
disable\u if\u c
将布尔值作为第一个参数

在[*]中,重要的是要注意函数必须是独占的。也就是说,如果对于给定的类型,有多个模板是候选模板,因为它们都不是其他模板的特化,编译器将因歧义错误而停止。这就是在最后一个模板中使用
禁用\u if
的原因

注意:我使用了
boost
名称空间而不是
std
,因为我从未在c++0x中使用过元编程,但我相信您可以在编译器中使用
std
更改
boost
名称空间。提前检查文档