I have a function f
that takes a string as input. I usually want to provide a string literal, e.g., f("hello")
. However, I want to implement another function g
that builds upon f
:
std::string f(const std::string&& x) {
return x " world";
}
std::string g(const std::string&& x) {
std::string res = f(x); // problem: rvalue reference to std::string cannot bind to lvalue of type std::string
res = "!";
return res;
}
int main() {
std::string res_a = f("hello");
std::string res_b = g("world");
return 0;
}
How can I achieve this in C 11/14 in a way that I can use f
with string literals as well as variables?
CodePudding user response:
A generic way of solving the problem of a function taking both l-value and r-value references is to use templated functions like so-
template <typename T>
T f(T&& val) {
}
template <typename T>
T g(T&& val) {
T some_val = f(std::forward<T>(val));
}
std::foward<T>(val)
forwards an l-value as an l-value and an r-value as an r-value, just as its name implies.
By templating the function, you ensure that this logic works for any type and not just strings.
CodePudding user response:
The traditional way to take a read-only parameter is by const
lvalue reference.
std::string f(const std::string& x)
This rule of thumb applies to many types, not just std::string
. The primary exceptions are types that are not bigger than a pointer (e.g. a char
).
It's rather unusual for a function to have a const
rvalue reference. As you discovered, that adds difficulty when trying to pass a variable as the argument. A non-const
rvalue reference has value, but a const
rvalue reference is inferior to a const
lvaue reference in most cases. See also Do rvalue references to const have any use?