【问题标题】:Template metaprogramming within the body of a template class模板类主体内的模板元编程
【发布时间】:2013-05-06 18:55:20
【问题描述】:

我正在尝试在模板类/结构体中编写部分专用的模板函数。部分特化用于执行递归模板元编程。

template<size_t N>
struct my_class {

template<size_t D> double my_func(...){}

template<> double my_func<0>(...){}

double other_func(...){ return my_func<N-1>(...); }
};

但是 g++(使用 -std=c++0x 选项)抱怨说不能在类/结构中部分专门化模板函数并迫使我编写模板函数 my_func 在单独的 namespace 中的类范围之外,就好像它们是静态的,最终传递所有 private 类变量并使代码非常混乱(所有this 容易引用的成员变量)。

有没有办法可以进行部分模板特化(我也可以将函数作为 my_class 的私有子类的静态成员)和在同一个类中进行元编程?

这使代码更简洁,更易于维护。 我使用的是 Ubuntu 12.04 和 gcc 4.6。

干杯

【问题讨论】:

    标签: c++ templates c++11 metaprogramming


    【解决方案1】:

    您可以通过重载函数(而不是专门化它)然后使用enable_if 选择性地仅启用一个或其他重载来实现所需的结果:

    template<size_t D> typename std::enable_if<D!=0, double>::type my_func(...){}
    
    template<size_t D> typename std::enable_if<D==0, double>::type my_func(...){}
    

    enable_if 约束意味着当D!=0 只有第一个重载是可行的函数时,D==0 只有第二个重载是可行的函数。

    在 C++03 中,您可以使用 boost::enable_if_c 做同样的事情。

    我首选的解决方案是用自定义特征类型替换丑陋的 enable_if 用法,可能是这样的:

    template<size_t> struct if_zero { typedef double disable; };
    template<> struct if_zero<0> { typedef double enable; };
    
    template<size_t D> typename if_zero<D>::disable my_func(...){}
    template<size_t D> typename if_zero<D>::enable  my_func(...){}
    

    这具有相同的效果,但更像literate programming 风格。

    另一种更容易阅读的形式是:

    template<bool, typename T> struct If_ { typedef T enable; };
    template<typename T> struct If_<false, T> { };
    
    template<bool B, typename T> using If = typename If_<B, T>::enable;
    
    template<size_t D> If<D!=0, double> my_func(...){}
    template<size_t D> If<D==0, double> my_func(...){}
    

    我认为"Concepts Lite" 提案将通过像这样约束第二个重载以更简洁的方式实现这一点:

    template<size_t D> double my_func(...){}
    
    template<size_t D> requires (D == 0)
      double my_func(...){}
    

    这里的第二个重载只能在D==0 时调用,并且将由重载决议选择,因为它比第一个重载更受约束。

    【讨论】:

    • SFINAE 赢得胜利吧? :-) 我真的希望新标准能够开箱即用地支持部分指定的模板元编程,没有这些丑陋的句法技巧......
    • 查看我添加的 If 别名模板版本,我认为这是您可以在 C++11 中获得的最佳语法。如果概念进入 C++17,您将能够使用约束。
    猜你喜欢
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    相关资源
    最近更新 更多