How to accumulate template parameter pack? - c++

Suppose I want to enable writing this:
template <int a,int b> struct add_base{ static const int value = a+b;};
template<int...a> using add = accumulate<add_base,0,a...>;
template <int a,int b> struct mult_base{ static const int value = a*b;};
template<int...a> using mult = accumulate<mult_base,1,a...>;
template <int a,int b> struct sqsum_base{ static const int value = a+b*b;};
template<int...a> using sqsum = accumulate<sqsum_base,0,a...>;
static_assert( add<1,2,3>::value == 6 );
static_assert( mult<2,2,2>::value == 8 );
static_assert( sqsum<1,2,3>::value == 14 );
My accumulate looks like this:
template <template <int,int> class G,
int first, int second,
int...more>
struct accumulate {
static const int value = accumulate<G,G<first,second>::value,more...>::value;
};
template <template <int,int> class G,
int first, int second>
struct accumulate<G,first,second> {
static const int value = G<first,second>::value;
};
Now I wonder if accumulate can be condensed by expanding the recusion inline, something like:
template <template <int,int> class G,
int first,int second,
int...more>
struct accumulate {
static const int value = G< G<first,second>::value , more...>::value;
};
This is wrong and will result in
error: Wrong number of template arguments (3 should be 2)
Is it possible to unpack the parameters to instantiate G recursively in one line? If not, how to write accumulate without having to write a specialization?

If your compiler has support for C++17 then you may want to utilize fold expression:
template<int ... x_item> struct
accumulate
{
static inline constexpr int const s_value{(0 + ... + x_item)};
};
static_assert(6 == accumulate<1, 2, 3>::s_value);
online compiler
Example of parametrized operation:
template<typename x_Op, int ... x_items> struct
accumulate
{
static inline constexpr int const s_value{(x_Op{0} + ... + x_Op{x_items}).value};
};
struct
sq_sum
{
int value;
};
inline constexpr sq_sum
operator +(sq_sum left, sq_sum right)
{
return sq_sum{left.value + right.value * right.value};
}
static_assert(14 == accumulate<sq_sum, 1, 2, 3>::s_value);
online compiler

Related

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

Nested C++ template with variadic

I was wondering if it was possible to have nested C++ template and still be able to access the template values ?
To explain, here is what I currently have:
template <int first, int... tail>
struct ConstIntVector:ConstIntVector<tail...>
{};
template <int first>
struct ConstIntVector<first>
{};
template<int f1, int... t1>
int prod(const ConstIntVector<f1, t1...>, const int* a) {
return f1 * (*a) + prod(ConstIntVector<t1...>(), a+1);
}
This way, I can access the f1 value in my prod function. But I would like to do it like this:
template<ConstIntVector<int f1, int... t1>>
int prod(const int* a) {
return f1 * (*a) + prod<ConstIntVector<t1...>>(a+1);
}
It is possible ?
Partial template specializations aren't allowed for member functions. But you can use a helper struct:
namespace detail
{
template <typename T>
struct prodHelper;
template <int f1, int... t1>
struct prodHelper<ConstIntVector<f1, t1...> >
{
static int eval(const int* a) {
return f1 * (*a) + prodHelper<ConstIntVector<t1...>>::eval(a+1);
}
};
}
template <typename T>
int prod(const int* a) {
return detail::prodHelper<T>::eval(a);
}
Another option would be to utilize ConstIntVector structs to carry useful information:
template <int First, int... Tail>
struct ConstIntVector {
constexpr static int value = First;
using tail = ConstIntVector<Tail...>;
};
template <int First>
struct ConstIntVector<First> {
constexpr static int value = First;
using got_no_tail = void;
};
template <class CIV, typename CIV::tail* = nullptr>
int prod(const int* a) {
return CIV::value * (*a) + prod<typename CIV::tail>(a+1);
}
template <class CIV, typename CIV::got_no_tail* = nullptr>
int prod(const int* a) {
return CIV::value * (*a);
}
Just be aware, that recursion is neither necessary nor desirable to solve these kinds of TMP problems. First, it is better to simply define your vector like this:
template <int... Is>
struct ConstIntVector{};
That way you can have zero length vectors as well, which is convenient in handling edge cases (witness the fact that std::array can be length 0).
Next, lets write our product function. We'll modify it in two ways: first we'll infer the integer by trivially passing our ConstIntVector by value, and second we'll use pack expansions to avoid recursion.
template<int... Is>
int prod(const int* a, ConstIntVector<Is...>) {
int index = 0;
int sum = 0;
int [] temp = {(sum += (a[index++] * Is))...};
return sum;
}
Usage:
std::vector<int> v{1,2,3};
using v2 = ConstIntVector<4,5,6>;
std::cerr << prod(v.data(), v2{});
Live example: http://coliru.stacked-crooked.com/a/968e2f9594c6b292
Link to example of highly optimized assembly: https://godbolt.org/g/oR6rKe.
How about
template<int I>
int prod(const int* a) {
return I * (*a);
}
template<int I, int I2, int... Is>
int prod(const int* a) {
return I * (*a) + prod<I2, Is...>(a + 1);
}

specialization of variadic templates with class templates

Here's an issue I ran across while playing with variadic templates. I have some code that uses specialization to count "interesting" types in a parameter pack like so:
template<typename... _Pp>
struct count;
template<>
struct count<>
{
static const int value = 0;
};
// ignore uninteresting types
template<typename _First, typename... _Rest>
struct count<_First, _Rest...>
{
static const int value = count<_Rest...>::value;
};
// add 1 for a pointer
template<typename _First, typename... _Rest>
struct count<_First*, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
// add 1 for a reference
template<typename _First, typename... _Rest>
struct count<_First&, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
// add 1 for an int
template<typename... _Rest>
struct count<int, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
This code works fine, but I run into problems if I want to use the same approach to count class templates:
// add 1 for a vector
template<typename... _Rest>
struct count<vector, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
The above code fails to compile, error is "expected a type, got 'vector'" on the line beginning with "struct count". I'm also unable to something simpler, all class templates accepting a single argument:
// add 1 for a class template with 1 type parameter
template<template<typename> class _First, typename... _Rest>
struct count<_First, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
}
This code also fails to compile, complaining of "expected a type, got '_First'" once again on the line beginning with "struct count". Is someone familiar with a way to accomplish this goal using this approach (i.e. some modification that I can make to one or both of the specializations that will get them to compile and perform the desired calculation at compile time)?
EDIT:
I want the parameter pack for vector to be unbound, similar to the following code for a simple container wrapper with variadic template-template parameters that also specializes on std::vector:
// pass a container as a parameter using variadic template-template
parameter
template<typename _Tp, template<typename...> class _C>
struct success
{
// not specialized for any container
static const bool is_specialized = false;
// data member of container type
_C<_Tp> c_;
};
// partial specialization of above for std::vector
template<typename _Tp>
struct success<_Tp, std::vector>
{
// specialized for vector
static const bool is_specialized = true;
// again, data member of container type
std::vector<_Tp> c_;
};
EDIT
Seems like the final answer is that what I want to do can't be accomplished, but I have found a way to reframe the problem so that I cans solve it. Many thanks to those who helped.
If I understand correctly what you want... yes, you can create a templated struct that can count "class templates", so you can write something like
count<std::vector, std::map, std::set, std::pair>::value
but you can't mix class templates and simple typenames, so you can't write something like
count<std::vector, int &, float, std::set>::value
The problem is that if you define
template <typename... _Pp>
struct count;
you can pass std::vector<int> to it, because std::vector<int> is a typename, but you can't pass std::vector to it because std::vector isn't a typename; it's a template<typename...> class (or template template) that it's a total different things.
You can write something like the following struct countC
template <template<typename...> class ...>
struct countC;
template <>
struct countC<>
{ static const int value = 0; };
// ignore uninteresting templates
template<template<typename...> class F, template<typename...> class ... R>
struct countC<F, R...>
{ static const int value = countC<R...>::value; };
template <template<typename...> class ... R>
struct countC<std::vector, R...>
{ static const int value = 1 + countC<R...>::value; };
The following is a working complete example where I've rewritten your struct count as struct countT for count selected types, I've added a struct countC to count selected "class templates" and I've added a struct countV to count selected values of a fixed typename.
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <iostream>
// countC for templates
template <template<typename...> class ...>
struct countC;
template <>
struct countC<>
{ static const int value = 0; };
// ignore uninteresting templates
template<template<typename...> class F, template<typename...> class ... R>
struct countC<F, R...>
{ static const int value = countC<R...>::value; };
template <template<typename...> class ... R>
struct countC<std::vector, R...>
{ static const int value = 1 + countC<R...>::value; };
template <template<typename...> class ... R>
struct countC<std::map, R...>
{ static const int value = 1 + countC<R...>::value; };
template <template<typename...> class ... R>
struct countC<std::pair, R...>
{ static const int value = 1 + countC<R...>::value; };
// countV for for values of a fixed type
template <typename T, T ... v>
struct countV;
template <typename T>
struct countV<T>
{ static const int value = 0; };
// ignore uninteresting values
template <typename T, T f, T ... r>
struct countV<T, f, r...>
{ static const int value = countV<T, r...>::value; };
// count only int odd values
template <int f, int ... r>
struct countV<int, f, r...>
{ static const int value = (f % 2) + countV<int, r...>::value; };
// countT for typenames
template <typename...>
struct countT;
template <>
struct countT<>
{ static const int value = 0; };
// ignore uninteresting types
template <typename F, typename ... R>
struct countT<F, R...>
{ static const int value = countT<R...>::value; };
template <typename F, typename ... R>
struct countT<F*, R...>
{ static const int value = 1 + countT<R...>::value; };
template<typename F, typename ... R>
struct countT<F&, R...>
{ static const int value = 1 + countT<R...>::value; };
template<typename ... R>
struct countT<int, R...>
{ static const int value = 1 + countT<R...>::value; };
int main()
{
std::cout << "countC vector + map + set + pair = "
<< countC<std::vector, std::map, std::set, std::pair>::value
<< std::endl;
std::cout << "countT int + float + bool* + double& + bool + int& = "
<< countT<int, float, bool*, double&, bool, int&>::value
<< std::endl;
std::cout << "countV int, 1 + 4 + 4 + 5 + 7 + 10 + 11 + 16 + 15 = "
<< countV<int, 1, 4, 4, 5, 7, 10, 11, 16, 15>::value
<< std::endl;
std::cout << "countV long, 1 + 4 + 4 + 5 + 7 + 10 + 11 + 16 + 15 = "
<< countV<long, 1, 4, 4, 5, 7, 10, 11, 16, 15>::value
<< std::endl;
return 0;
}
p.s.: sorry for my bad English.
How about something like this?
// add 1 for a vector
template<typename... _Rest, typename T>
struct count<vector<T>, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
And this?
// add 1 for a class template with 1 type parameter
template<template<typename> class _First, typename T, typename... _Rest>
struct count<_First<T>, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
It should be:
template<typename... _Rest, typename... T>
struct count<std::vector<T...>, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
Generic version:
template<template<typename...> class C, typename... _Rest, typename... T>
struct count<C<T...>, _Rest...>
{
static const int value = 1 + count<_Rest...>::value;
};
Variadic pack matters.

Initialise static const int with static function

I have a template class with some integers as arguments. One static const integer (call it Length) of this class needs to be calculated based on the arguments. The calculation does need a loop (as far as I know) so a simple expression won't help.
static int setLength()
{
int length = 1;
while (length <= someTemplateArgument)
{
length = length << 1;
}
return length;
}
The returned length should be used to init Length. Lengthis used as a fixed length of an array so I need it to be constant.
Is there a solution for this issue? I know that constexp could help but I can't use C11 or later.
Using metaprogramming. Implementation of C++11 enable_if taken from cppreference.com
#include <iostream>
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
template <int length, int arg, typename = void>
struct length_impl
{
static const int value = length_impl<(length << 1), arg>::value;
};
template <int length, int arg>
struct length_impl<length, arg, typename enable_if<(length > arg)>::type>
{
static const int value = length ;
};
template <int arg>
struct length_holder
{
static const int value = length_impl<1, arg>::value;
};
template<int n>
struct constexpr_checker
{
static const int value = n;
};
int main()
{
std::cout << constexpr_checker< length_holder<20>::value >::value;
}

float or double in templated code

The following example might seem nonsensical, but it's part of a larger high-performance code where the presented technique makes sense. I mention this just in case someone should suspect an XY question - it's most probably not.
I have a function with templated/compile-time operand:
template <int M>
int mul(int x){
return M * x;
}
Now I want to do the same for double, what is - of course - not allowed:
template <double M> // you can't do that!
int mul(double x){
return M * x;
}
So to still put in the double at compile time, I only see the following solution:
// create my constants
struct SevenPointFive{
static constexpr double VAL = 7.5;
}
struct ThreePointOne{
static constexpr double VAL = 3.1;
}
// modified function
template <class M>
int mul(double x){
return M::VAL * x;
}
// call it
double a = mul<SevenPointFive>(3.2);
double b = mul<ThreePointOne>(a);
Is there a better solution for the problem to somehow pass a double constant in a template parameter, without creating a struct for each value?
(I'm interested in a solution which actually uses double/float, not a hack with using two ints to create a rational number or fixed point ideas such as y = 0.01 * M * x.)
In C++11, it is not necessary to use templates at all. Simply use constexpr (generalised constant expressions) in a different way than you are.
#include <iostream>
constexpr double mul(double x, double y)
{
return x*y;
}
int main()
{
std::cout << mul(2.3, 3.4) << '\n';
double x;
std::cin >> x; // to demonstrate constexpr works with variables
std::cout << mul(2.3, x) << '\n';
}
Although I say templates aren't necessary (which they aren't in the example given) these can be templated if needed
template <class T> constexpr T mul(T x, T y) {return x*y;}
or (if you want to use the function for types that are better passed by const reference)
template <class T> constexpr T mul(const T &x, const T &y) {return x*y;}
You can conveniently pass floating point values in template parameters using user-defined literals.
Just write a literal that creates your envelope class. Then you can write something like
mul<decltype(3.7_c)>(7)
Or even better, have your function take the argument by value so you can write
mul(3.7_c, 7)
the compiler will make that just as efficient.
Below's an example of code that does this:
#include <iostream>
template <int Value, char...>
struct ParseNumeratorImpl {
static constexpr int value = Value;
};
template <int Value, char First, char... Rest>
struct ParseNumeratorImpl<Value, First, Rest...> {
static constexpr int value =
(First == '.')
? ParseNumeratorImpl<Value, Rest...>::value
: ParseNumeratorImpl<10 * Value + (First - '0'), Rest...>::value;
};
template <char... Chars>
struct ParseNumerator {
static constexpr int value = ParseNumeratorImpl<0, Chars...>::value;
};
template <int Value, bool, char...>
struct ParseDenominatorImpl {
static constexpr int value = Value;
};
template <int Value, bool RightOfDecimalPoint, char First, char... Rest>
struct ParseDenominatorImpl<Value, RightOfDecimalPoint, First, Rest...> {
static constexpr int value =
(First == '.' && sizeof...(Rest) > 0)
? ParseDenominatorImpl<1, true, Rest...>::value
: RightOfDecimalPoint
? ParseDenominatorImpl<Value * 10, true, Rest...>::value
: ParseDenominatorImpl<1, false, Rest...>::value;
};
template <char... Chars>
using ParseDenominator = ParseDenominatorImpl<1, false, Chars...>;
template <int Num, int Denom>
struct FloatingPointNumber {
static constexpr float float_value =
static_cast<float>(Num) / static_cast<float>(Denom);
static constexpr double double_value =
static_cast<double>(Num) / static_cast<double>(Denom);
constexpr operator double() { return double_value; }
};
template <int Num, int Denom>
FloatingPointNumber<-Num, Denom> operator-(FloatingPointNumber<Num, Denom>) {
return {};
}
template <char... Chars>
constexpr auto operator"" _c() {
return FloatingPointNumber<ParseNumerator<Chars...>::value,
ParseDenominator<Chars...>::value>{};
}
template <class Val>
int mul(double x) {
return Val::double_value * x;
}
template <class Val>
int mul(Val v, double x) {
return v * x;
}
int main() {
std::cout << mul<decltype(3.79_c)>(77) << "\n";
std::cout << mul(3.79_c, 77) << "\n";
return 0;
}
constexpr double make_double( int64_t v, int64_t man );
write a function that makes a double from a base and mantissa. This can represent every non-special double.
Then write:
template<int64_t v, int64_t man>
struct double_constant;
using the above make_double and various constexpr access methods.
You can even write base and exponent extracting constexpr functions I suspect. Add a macro to remove DRY, or use a variable.
Another approach is:
const double pi=3.14;//...
template<double const* v>
struct dval{
operator double()const{return *v;}
};
template<class X>
double mul(double d){
return d*X{};
}
double(*f)(double)=mul<dval<&pi>>;
which requires a variable to point to, but is less obtuse.
If you don't want to create type envelopes for each double/float constant used, then you can create a mapping between integer and double constants. Such mapping can be implemented e.g. as follows:
#include <string>
#include <sstream>
template<int index> double getValue()
{
std::stringstream ss("Not implemented for index ");
ss << index;
throw std::exception(ss.str());
}
template<> double getValue<0>() { return 3.6; }
template<> double getValue<1>() { return 7.77; }
template<int index> double multiply(double x)
{
return getValue<index>() * x;
}
Alternative options to implement the mapping are via a function which does switch-case on the input integer parameter and returns a float/double, or indexing to an array of constants, but both these alternatives would require constexpr for them to happen on compile-time, while some compilers still do not support constexpr: constexpr not compiling in VC2013