Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine class template default parameters and variadic parameters

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 ?

like image 938
thomas Avatar asked Jan 24 '26 23:01

thomas


1 Answers

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;
like image 133
llllllllll Avatar answered Jan 27 '26 18:01

llllllllll



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!