Question

I'm writting a policy based logging system while learning a bit of C++ as a hobby. Seems to be a pretty classic exercise. But I have run into a problem I can't solve.

I'm using a variadic template to pass any parameters in the Sink constructorto the writerPolicy as some of the policies need a parameter.

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;
    }; 

The headache starts when I realise that the other policies also might need zero or more parameters passed on to them in the constructor of sink.

Obviously we can't write:

Sink(T1s ... v1s, T2s ... v2s, T3s ... v3s) : m_filter(v1s...), m_formatter(v2...), m_writer(v3s...){}

But I can't get my head around this template thing and come up with a good solution, that lets the Sink template figure out which arguments go with witch policies.

My goal is to be able to write

Sink<FilterOnLogLevelPolicy,HTMLFormatPolicy,FileWriterPolicy>(log::DEBUG,"log.html");

and have Sink pass the first argument to FilerOnLogLevelPolicy (which takes one parameter in its constructor), none to HTMLFormatPolicy which takes no parameter and the 2nd argument to FileWriterPolicy which needs a filename in the constructor.

HOW?

Était-ce utile?

La solution

Why not "outsource" the construction to the client, they're her types anyway so she knows how to build them (see 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;
};

This results in the declaration syntax:

Sink<FilterOnLogLevelPolicy,HTMLFormatPolicy,FileWriterPolicy> sink(
  {log::DEBUG}, {}, {"log.html"}
);

Allowing the user to perform as complicated or as simple an initialization as she likes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top