Skip to main content
added 1106 characters in body
Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

This gets rid of the us-less function:

    template<typename A>
    void forward(A const&...) const{}

We converted struct Printer into a function call printValue().

    template<typename A>
    std::ostream& printValue(std::ostream&      s,
                             std::string const& prefix,
                             Formatter const&   format,
                             A const&           value) const

This means the compiler could do argument type deduction. So the call could be simplified:

 // from 
 Printer<decltype(std::get<I>(arguments))>(s, prefixString[I], formater[I], std::get<I>(arguments))...

 // too
 printValue(s, prefixString[I], formater[I], std::get<I>(arguments))...

But now that it is a function (rather than a class) it has accesses to the members. So we don't actually need to pass all those parameters. So we can simplify even more:

 // too
 template<std::size_t I>
 std::ostream& printValue(std::ostream& s) const

 // Now the call is simply
 printValue<I>(s)...

This gets rid of the us-less function:

    template<typename A>
    void forward(A const&...) const{}

We converted struct Printer into a function call printValue().

    template<typename A>
    std::ostream& printValue(std::ostream&      s,
                             std::string const& prefix,
                             Formatter const&   format,
                             A const&           value) const

This means the compiler could do argument type deduction. So the call could be simplified:

 // from 
 Printer<decltype(std::get<I>(arguments))>(s, prefixString[I], formater[I], std::get<I>(arguments))...

 // too
 printValue(s, prefixString[I], formater[I], std::get<I>(arguments))...

But now that it is a function (rather than a class) it has accesses to the members. So we don't actually need to pass all those parameters. So we can simplify even more:

 // too
 template<std::size_t I>
 std::ostream& printValue(std::ostream& s) const

 // Now the call is simply
 printValue<I>(s)...
Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

We can simplify the parameter pack unpacking a bit:

private:
    // The template parameter is the index of the argument we are printing.
    // Generated from the doPrint() function.
    template<std::size_t I>
    std::ostream& printValue(std::ostream& s) const
    {   
        return s << prefixString[I] << formater[I] << std::get<I>(arguments);
    }   

    // Called from print()
    //    The std::index_sequence<> is constructed based on the number of
    //    arguments passed to the constructor. This mean I is a sequence
    //    of numbers from 0 ... A   (A is one less the number of param)
    //    We can use this to call printValue() A times using parameter
    //    pack expansion.
    template<std::size_t... I>
    void doPrint(std::ostream& s, std::index_sequence<I...> const&) const
    {   
        std::ostream* ignore[] = {&printValue<I>(s)...};
        s << prefixString.back();
    }