Consider we need to implement a function f with a templated argument T t. The function should not copy t and accept both rvalues and lvalues, therefore two implementations are possible:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
If we want to change t inside of f or need to preserve the value category, we have to use the second version. So by this line of thought when and why would we go for the first option?
You'll mainly go for the first option when you want to give strong guarantee to the clients of your function that t won't be changed inside of f. Although you can drop the const qualifier and still not modify t, it's considered good practice and good interface design to qualify as const a parameter if you don't change it's referred to value inside a function, plus it helps the compiler to optimize the code better.
As an extra, know that you can use const_cast to hack around the type safety of const if you really must, but recall that you're doing exactly that: getting rid of the type safety. Avoid this at all cost.
And lastly, a const qualifier doesn't prevent copying, you can easily do something like:
int main()
{
const int a = 3;
int b = a; // a is copied to b
}
In this generic scenario, there is no reason to write both overloads.
If f will only observe its argument, then only the const T& overload is needed.
If f will just forward its argument to some other function, then only the T&& overload is needed, and will use std::forward<T>. (This includes the case where the function needs to retain a copy of the value, i.e., forward it to a copy/move constructor.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With