【发布时间】:2018-02-23 16:37:27
【问题描述】:
我正在设计一个 Host 类,它使用固定数量的 Policies 类,大约 3 或 4 个。
因为对于设计中的每个Policy,总会有一个琐碎的实现,因此最好将模板参数默认为琐碎类型,以方便其客户使用Host 类。
class IdiotBenchPolicy {};
class IdiotLoggerPolicy {};
// ...
template <typename BenchmarkPolicy = IdiotBenchPolicy,
typename LoggerPolicy = IdiotLoggerPolicy>
class Host
{
BenchmarkPolicy m_bench;
IdiotLoggerPolicy m_logger;
};
这允许实例化Host,而无需指定一长串模板参数。
这很好,直到Host 类还必须采用可变数量的算术类型。拆分问题时,忘记Policies,我可以使用可变参数模板参数:
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;
};
请注意,即使Host 在内部使用元组,除非必要,否则最好不要在类客户端上强制执行它。
我现在的问题是将这两种行为结合起来。如果“默认”足够,如何实例化Host 类而无需指定Policies。我不知道如何用 C++ 模板语法来表达这一点,但我的直觉告诉我可以通过 SFINAE 和 std::enable_if 来实现,但是我很难理解如何。
我希望能够写的是:
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
如何实现这样一个Host 类,可以使用类似于上面指定的实例化来构造?
【问题讨论】:
-
一种解决方法可能是期望
TypeListHolder<Args...>(带有template<class...> class TypeListHolder)而不是Args...,并通过type_list<int, float /*...*/>(带有template<class...> struct type_list {};)而不是int, float /*...*/ -
另外,您可以让特征类告诉您一个类是否是合适的策略,并根据第一个模板参数是“合适的策略类”还是用于可变参数包的看似任意类型进行专门化。
-
@Caninonos 我考虑过你的第二个解决方案,但据我所知,这意味着
Host仅将Args...作为模板参数,然后尝试将每个 Arg 解压缩到使用策略特征的策略类型之一。我只想写一次Host的实现,所以这意味着从专业中调用主模板版本? -
嗯,基本上,你可以这样做:ideone.com/FokpOQ 并利用继承来避免重写 Host 的实现。
-
@Caninonos 这里继承是公开的,但我认为可以私下继承并在
Host中定义bench方法,然后从内部调用tell_me_what_you_chose?是否可以将组合与Host_aux一起使用?
标签: c++ templates variadic-templates