Let's assume i want to define a type that depends on some types:
struct TimerPump{};
struct GuiPump{};
struct NetworkPump{};
template<class... Pumps>
class DispatcherT{};
using Dispatcher = DispatcherT< TimerPump, GuiPump, NetworkPump >;
I would like to make the gui and network pumps be optional. Either one might be needed or both or none. I could write a preprocessor macro:
using Dispatcher = DispatcherT< TimerPump
#ifdef GUI_ENABLED
, GuiPump
#endif
#ifdef NETWORK_ENABLED
, NetworkPump
#endif
>;
but i'm looking for a way to control those arguments through traits
struct Traits
{
static constexpr bool gui = true;
static constexpr bool network = false;
};
using Dispatcher = DispatcherT< TimerPump
, Traits::gui ? GuiPump : null <--- need help here
, Traits::network ? NetworkPump : null
>;
Is there a neat way to determine arguments passed to a template taking variadic arguments?
CodePudding user response:
Basically, you'd like optional list append. To do that, you first need list append:
template<typename... Ts>
struct list {
template<typename T>
using append = list<Ts..., T>;
template<bool b, typename T>
using appendIf = std::conditional_t<b, list<Ts..., T>, list<Ts...>>;
template<template<class...> LT>
using applyTo = LT<Ts...>;
};
Then you might start with list<>
(or whatever types you surely have), then, at each step, use ::appendIf<condition, type>
and end with applyTo<DispatcherT>
.
using Dispatcher =
list<TimerPump>
::appendIf<Traits::gui, GuiPump>
::appendIf<Traits::network, NetworkPump>
::applyTo<DispatcherT>;