代码之家  ›  专栏  ›  技术社区  ›  left click

如何使用运算符专门化模板?

  •  1
  • left click  · 技术社区  · 5 年前

    我想用TMP把数字从1加到N-1。因此,我编写了如下所示的源代码,但出现了一个错误 template argument '(number - 1)' involves template parameter(s) 发生。你知道怎么处理吗?

    template <int number, int i = 1>
    class Sum {
        public:
            static const int result = i + Sum<number, i + 1>::result;
    };
    
    template <int number>
    class Sum<number, number - 1> {
        public:
            static const int result = number - 1;
    };
    
    int main () {
        const int result = Sum<10>::result;
        return 0;
    }
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   Evg    5 年前

    GCC仍然紧随其后 the rule

    非类型参数表达式不能使用模板参数的名称,除非它正好是模板参数的名称。

    要使用模板专门化解决此问题,可以将第二个非类型模板参数包装到 std::integral_constant 要使其成为类型模板参数,请执行以下操作:

    template<int number, class i = std::integral_constant<int, 1>>
    struct Sum {
        static constexpr int value = i() + Sum<number, 
           std::integral_constant<int, i() + 1>>::value;
    };
    
    template<int number>
    struct Sum<number, std::integral_constant<int, number - 1>> {
        static constexpr int value = number - 1;
    };
    
    static_assert(Sum<10>::value == 45);
    

    或者,你可以使用 if constexpr 没有部分专业化:

    template<int number, int i = 1>
    struct Sum {
        static constexpr int value = [] {
            if constexpr (number == i + 1)
                return i;
            else 
                return i + Sum<number, i + 1>::value;
        }();
    };
    
    static_assert(Sum<10>::value == 45);
    

    折叠表达式给出了另一种方式:

    template<class> struct Sum_impl;
    
    template<int... numbers>
    struct Sum_impl<std::integer_sequence<int, numbers...>> {
        static constexpr int value = (... + numbers);
    };
    
    template<int number>
    struct Sum : Sum_impl<std::make_integer_sequence<int, number>> {};