Template Metaprogramming: Multiplying a bunch of template arguments

I need to compute the product of a bunch of numbers at compile time, passed in a template structure. I managed to make the ugly decision:

template<std::size_t n1, std::size_t ...args> struct mul_all { static constexpr std::size_t value = n1 * mul_all<args...>; }; template<> struct mul_all<0> { static constexpr std::size_t value = 1; }; 


The problem is that every time I have to feed 0 into the template arguments for my structure, for example:

 int main() { std::cout << mul_all<1,2,5,4,5,7,0>::value << " " << mul_all<4,2,0>::value; return 0; } 


is there any workaround to read this last zero?

Note: I am starting in TMP.

+6
source share
4 answers

In C ++ 17, with a bend expression, you can directly do

 template<std::size_t ...args> struct mul_all { static constexpr std::size_t value = (args * ...); }; 

Before that, you should perform a partial specialization:

 template<std::size_t n1, std::size_t ...args> struct mul_all { static constexpr std::size_t value = n1 * mul_all<args...>::value; }; template<std::size_t n> struct mul_all<n> { static constexpr std::size_t value = n; }; 
+6
source

You need to replace your specialization:

 template<std::size_t n1, std::size_t ...args> struct mul_all { static constexpr std::size_t value = n1 * mul_all<args...>::value; }; template<std::size_t n> struct mul_all<n> { static constexpr std::size_t value = n; }; 
+5
source

One way is to specialize for empty varargs. To do this, you need the main template to be just a variable argument:

 // main template never used template<std::size_t ...args> struct mul_all { }; // specialization for at least one arg template<std::size_t n1, std::size_t ...args> struct mul_all<n1, args...> { static constexpr std::size_t value = n1 * mul_all<args...>::value; }; // specialization for empty args template<> struct mul_all<> { static constexpr std::size_t value = 1; }; 

So now you can do:

 mul_all<1, 2, 3>::value; 
+3
source

The C ++ 17 approach makes this nice and easy:

 template <std::size_t... A> constexpr std::size_t mul = (A * ... * std::size_t(1u)); int main() { constexpr std::size_t val = mul<1, 2, 3, 4>; } 

For existing C ++ versions, you need to partially highlight the case of mul<v> :

 template <std::size_t... V> struct mul; template <std::size_t V> struct mul { statuc constexpr std::size_t value = V; }; template <std::size_t V, std::size_t... T> struct mul { statuc constexpr std::size_t value = V * mul<T...>::value; }; template <std::size_t... V> using mul_v = mul<V...>::value; int main() { constexpr std::size_t v = mul_v<1, 2, 3, 4>; } 
+2
source

Source: https://habr.com/ru/post/1013667/


All Articles