left click
left click

Reputation: 894

How to specialize template using operator?

I want to sum the number from 1 to N-1 by TMP. so I wrote a source code as shown below, but an error template argument '(number - 1)' involves template parameter(s) occurred. Do you happen to know how to deal with this?

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;
}

Upvotes: 2

Views: 61

Answers (1)

Evg
Evg

Reputation: 26282

GCC still follows the rule:

Non-type argument expression cannot use the name of the template parameter except when it is exactly the name of the template parameter.

To solve the problem using template specialization, you can wrap the second non-type template parameter into an std::integral_constant to make it a type template parameter:

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);

Alternatively, you can use if constexpr and no partial specialization:

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);

Yet another way is given by fold expressions:

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>> {};

Upvotes: 1

Related Questions