我正在编写基于策略的日志记录系统,同时学习一些C ++作为业余爱好。似乎是一个非常经典的练习。但是我遇到了一个我无法解决的问题。
我正在使用一个可变参数模板在Sink构造中传递writerPolicy中的任何参数,因为某些策略需要一个参数。
template <class FilterPolicy, class FormatterPolicy ,class WriterPolicy, class ...Ts>
class Sink
{
public:
Sink(Ts ... p_args) : m_filter(), m_formatter(), m_writer(p_args...){}
virtual void ProcessLogEntry(const Log::LogEntry &data) ;
private:
FilterPolicy m_filter;
FormatterPolicy m_formatter;
WriterPolicy m_writer;
};
当我意识到其他策略也可能需要在sink的构造函数中传递给它们的零个或多个参数时,头痛就开始了。
显然我们不能写:
Sink(T1s ... v1s, T2s ... v2s, T3s ... v3s) : m_filter(v1s...), m_formatter(v2...), m_writer(v3s...){}
但我不能理解这个模板的事情,并想出一个很好的解决方案,让Sink模板找出哪些参数与女巫政策有关。
我的目标是能够写
Sink<FilterOnLogLevelPolicy,HTMLFormatPolicy,FileWriterPolicy>(log::DEBUG,"log.html");
并让Sink将第一个参数传递给FilerOnLogLevelPolicy(在其构造函数中接受一个参数),没有传递给不带参数的HTMLFormatPolicy,第二个参数传递给构造函数中需要文件名的FileWriterPolicy。
如何吗
答案 0 :(得分:3)
为什么不将建筑“外包”给客户,无论如何都是她的类型,所以她知道如何建造它们(见Dependency Injection)。
template <class FilterPolicy, class FormatterPolicy, class WriterPolicy>
class Sink
{
public:
Sink(FilterPolicy filter,
FormatterPolicy formatter,
WriterPolicy writer) :
m_filter(std::move(filter)),
m_formatter(std::move(formatter)),
m_writer(std::move(writer)) {}
virtual void ProcessLogEntry(const Log::LogEntry &data);
private:
FilterPolicy m_filter;
FormatterPolicy m_formatter;
WriterPolicy m_writer;
};
这会产生声明语法:
Sink<FilterOnLogLevelPolicy,HTMLFormatPolicy,FileWriterPolicy> sink(
{log::DEBUG}, {}, {"log.html"}
);
允许用户执行她喜欢的复杂或简单的初始化。