Skip to main content
Code Review

Return to Revisions

2 of 2
Commonmark migration

The biggest thing that sticks out at me is that you're passing all of your Args... parameters by value, thus pretty much making std::forward useless here. To make use of std::forward, the reference type needs to be deduced from the calling context. By itself, std::forward really doesn't do anything except a static_cast to the deduced reference type.

Basically, everywhere you have Args should be passed by Args&&:

template<typename T, typename ...Args>
void writeln(T firstArg, Args&&... extraArgs)
template<typename T, typename ...Args>
std::string format(T firstArg, Args&&... extraArgs)

As a cut down example of the difference this makes, try this example:

#include <memory>
#include <iostream>
struct s
{
 s()
 { }
 
 s(s&& )
 {
 std::cout << "Move\n";
 }
 
 s(const s& )
 {
 std::cout << "Copy\n";
 }
};
template <typename T>
void do_forward(T&& v)
{
 sink(std::forward<T>(v));
}
template <typename U>
void sink(U&& u)
{
 std::cout << "In sink\n";
}
int main()
{
 s something;
 do_forward(something);
}

If I run this, the output is:

In sink

If I change the signature of do_foward and sink to:

template <typename T>
void do_forward(T v)
template <typename U>
void sink(U u)

The output is:

Copy

Move

In sink

If we change main to just pass an actual rvalue reference instead of an lvalue:

int main()
{
 do_forward(s{});
}

We remove the first copy operation (from do_forward) but still have a move operation (in sink).

Yuushi
  • 11.1k
  • 2
  • 31
  • 66
default

AltStyle によって変換されたページ (->オリジナル) /