I am designing a Host class that uses a fixed number of Policies classes, around 3 or 4.
Because for each Policy in the design there will always be a trivial implementation, it would be nice to default the template parameter to the trivial type, in order to ease the use of the Host class by its clients.
class IdiotBenchPolicy {};
class IdiotLoggerPolicy {};
// ...
template <typename BenchmarkPolicy = IdiotBenchPolicy,
typename LoggerPolicy = IdiotLoggerPolicy>
class Host
{
BenchmarkPolicy m_bench;
IdiotLoggerPolicy m_logger;
};
This allow to instantiate a Host without having to specify a long list of template parameters.
This is fine until the Host class must also take a variable number of arithmetic types. When splitting the problem, and forgetting about the Policies, I am able to use a variadic template parameter:
template <class... Args>
class Host
{
template <class ...Var_Args>
using are_arithmetic = typename std::conjunction<std::is_arithmetic<Var_Args>...>::type;
static_assert(are_arithmetic<Args...>::value, "Args are not all arithmetic type");
std::tuple<Args...> m_args;
};
Note that even though Host uses a tuple internally, It'd be better not to enforce it on the class clients unless necessary.
My problem now, is to combine the two behaviors. How to instantiate a Host class without having to specify the Policies if the "default" is sufficient. I am not sure how to express this with C++ template syntax, but my intuition tells me it is possible by juggling with SFINAE and std::enable_if, however I struggle to see how.
What I'd like to be able to write is:
Host<int, int, float> h; //Using both default policies
Host<SmarterBenchPolicy, float, double> h2; //Using SmarterBenchPolicy, IdiotLoggerPolicy and two arithmetic types
Host<SmarterBenchPolicy>; //Using SmarterBenchPolicy, IdiotLoggerPolicy and no arithmetic type
How such a Host class, that is constructible using instantiations similar to those specified above, would be implemented ?
I think it would be better if you put those parameters with default values at the and of the parameter list. The variadic parameters can be packed into a std::tuple:
template <class ArgsPack,
typename BenchmarkPolicy = IdiotBenchPolicy,
typename LoggerPolicy = IdiotLoggerPolicy,
std::enable_if_t<detail::is_tuple<ArgsPack>::value, int> = 0
>
struct Host
{
BenchmarkPolicy bench;
LoggerPolicy logger;
ArgsPack args;
void show_all() {
detail::tuple_foreach([](const auto &e) {std::cout << e << "\n";}, args);
}
};
Host<std::tuple<int, int, float>, SmartBenchPolicy> h;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With