多个typename的部分模板特化

时间:2010-12-25 09:02:33

标签: c++ templates c++11 return-type template-specialization

在以下代码中,我想考虑将Op返回的函数(void s)视为返回true。类型RetvalOp的返回值始终匹配。我无法使用此处显示的类型特征进行区分,并且由于存在其他模板变量Retval和{{1},尝试基于Op创建部分模板特化失败}。

如何在模板专业化中仅对某些变量进行专门化而不会出现错误?是否有其他方法可以根据Args的返回类型更改行为?

Op

3 个答案:

答案 0 :(得分:1)

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

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

编辑:忘了你在写一个函数,而不是一个类。

答案 1 :(得分:0)

模板功能不能部分专业化。您可以执行以下操作:您可以使用单个静态方法将函数包装到类模板中并专门化类模板,或者您可以使用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 [+]的单独模板上:

在C ++中,你不能拥有一个带有void类型参数的函数。这意味着您不能使用与void案例相同的参数,因为您正在使用其他参数。

在元编程方面:

这里有一些棘手的问题...... enable_if是一个元函数,如果条件满足则定义内部类型,否则不定义。当编译器尝试替换模板中的类型时,如果满足条件,则返回类型将仅有效(并且因此该函数是候选函数)。 disable_if元函数具有相反的行为。直接变量enable_if / disable_if将元函数作为第一个参数,并选择将类型作为第二个参数。第二个版本enable_if_c / disable_if_c将布尔值作为第一个参数。

在[*]中注意功能必须是独占的。也就是说,如果对于给定类型,不止一个模板是候选模板,因为它们都不是其他模板的特化,编译器将以模糊错误停止。这就是在最后一个模板中使用disable_if的原因。

注意:我使用了boost命名空间而不是std,因为我没有在c ++ 0x中使用元编程,但我相信您可以使用boost命名空间更改std命名空间编译器中的{{1}}。提前检查文档!

答案 2 :(得分:0)

这是我用来绕过 C++ 中函数缺少部分模板特化的技巧。基本上,这依赖于函数重载和多个函数声明之间的灰色区域,由于 SFINAE 规则,这些函数声明不会导致编译器错误(所有 enable_if_t 布尔条件都是互斥的,因此给定任何特定编译单元,只有一个声明是有效的上下文)


template < class T, std::enable_if_t< sizeof(T) == 4, int > = 0 >
T do_transform(T inp) {
  // 4 byte implementation
}


template < class T, std::enable_if_t< sizeof(T) == 8, int > = 0 >
T do_transform(T inp) {
 // 8 byte implementation
}

template <class T, std::enable_if_t< sizeof(T) > 8, int> = 0 >
T do_transform(T inp) {
 // very much wide word types
}