I am trying to understand what is the best way to handle a template class with many non-typename parameters.
What I want to avoid is something like:
template <int parameter1,
int parameter2,
int parameter3,
...
int parameterN>
class Foo {
void bar();
};
template <int parameter1, int parameter2, int parameter3, ..., parameterN>
void Foo::bar() {
// a function of parameter1, parameter2, ..., parameterN
}
One possible solution is packing constexpr inside a struct, like this:
struct ParametersSetA {
static constexpr int parameter1 = ...;
...
static constexpr int parameterN = ...;
};
template <typename ParametersSet>
class Foo {
void bar();
};
template <typename ParametersSet>
void Foo::bar() {
// a function of ParametersSet::parameter1, ..., ParametersSet::parameterN
}
This is a pretty subjective question (define "best"). IMO, using a struct would be ideal. But using structs as template parameters is only supported in C++20.
struct Config {
int a;
int b;
int c;
};
template <Config config>
struct Foo {
int bar(int a, int b, int c) {
return config.A*a + config.B*b + config.c*c;
}
};
/* ... */
Foo<Config {1, 2, 3}> foo;
I have seen parameters hidden using a type:
template <int A, int B, int C>
struct ConfigPack {};
template <typename Config>
struct Foo {
int bar(int a, int b, int c);
};
/* ... */
using Config = ConfigPack<1, 2, 3>;
Foo<Config> foo;
And then either overloading or partial specialization used for those methods which actually need the parameters:
template <int A, int B, int C>
int multiply_accumulate(int a, int b, int c, ConfigPack<A, B, C>) {
return A*a + B*b + C*c;
}
template <typename Config>
int Foo::bar(int a, int b, int c) {
return multiply_accumulate(a, b, c, Config{});
}
For your contrived example, with all the parameters being the same type and combined in a formulaic way, you can use a variadic template to simplify the formula (or depending on your point of view, make it horribly more complicated than it needs to be):
template <int... Is>
class Foo {
// using C++17 fold expressions
void bar(decltype(Is)... args) {
return ((Is * args) + ...);
}
// a bit less elegant, but works in C++11
void bar(decltype(Is)... args) {
auto terms = { (Is * args)... };
return std::accumulate(terms);
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.