Why do we want perfect forwarding?

Hi,

why should we use this code:

 
do_print(std::forward<T>(arg));



instead of

 
do_print(arg);


I understand the first code will respect the lvalue or rvalue type of the arg (doing perfect forwarding), but why would we care the parameter remains lvalue or rvalue??


what is a real world example where we care the parameter's value category is important?

This only matters if do_print might handle rvalue arguments differently (e.g. more efficiently) than lvalue arguments. If you know that do_print always takes its argument by const ref then there is no point in using std::forward here.
Last edited on
Examples of where perfect forwarding is useful:

* the "emplace" functions on containers
https://en.cppreference.com/w/cpp/container/set/emplace
https://en.cppreference.com/w/cpp/container/vector/emplace_back

* the "make" functions for smart pointers
https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared

These functions use perfect forwarding, to forward the arguments to the constructors.

For example, if the object that is being constructed is a std::vector<int> and you pass a temporary std::vector<int> object as argument to the function, then perfect forwarding allows the temporary object to be "moved" by the constructor.

1
2
3
4
5
6
7
8
std::vector<int> f()
{
	return {1, 2, 3};
}

std::set<std::vector<int>> s;

s.emplace(f());

Thanks to perfect forwarding, this calls the move constructor rather than the copy constructor, so there is no copying of the vector elements in the above example.
Last edited on
Does this code demonstrates the advantage of using perfect forwarding?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void do_the_print(string n)
{}

void do_print(const string& s)
{
	do_the_print(s);
}
void do_print(string&& t)
{
	do_the_print(std::move(t));   /// THIS HERE IS THE ADVANTAGE
}
template<typename T>
void printer(T&& arg)
{
	do_print(arg);
	do_print(std::forward<T>(arg));
}
string get_string()
{
	return "Hey hello!"s;
}
void call_print()
{
	do_print(get_string());
	printer(get_string());
	string str{ "Goodbye" };
	printer(str);
}


Last edited on
Topic archived. No new replies allowed.