'C++: Pass string literal or variable to function

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?



Solution 1:[1]

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?

Solution 2:[2]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JaMiT
Solution 2 Pavan Manjunath