Search code examples
c++implicit-conversionforwarding-reference

Forwarding references and converting constructors in C++


Suppose I want to create a function that takes both lvalue and rvalue string arguments by refernce, converts them to upper case, and prints them to standard output:

void upper_print(std::string& s);
void upper_print(std::string&& s);

This works fine as follows:

std::string s("Hello world");
upper_print(s);
upper_print(std::string("Hello world"));
upper_print("Hello world"); // converting ctor used

However, to avoid redundancy, I want to use a forwarding reference instead:

template <typename T> upper_print(T&& s);

Unfortunately, then I cannot invoke upper_print with a string literal argument:

std::string s("Hello world"); // OK
upper_print(s); // OK
upper_print(std::string("Hello world")); // OK
upper_print("Hello world"); // ERROR

I am aware of the possibility to restrict arguments to std::string objects, e.g., by using std::enable_if or static_assert. But it does not help here.

Is there any option to combine the functionality of forwarding references and converting constructor in this sense?


Solution

  • Maybe a solution like this?

    template <typename T>
    void upper_print_helper(T&& s);
    
    inline void upper_print(std::string&& s) {
        upper_print_helper(std::move(s));
    }
    inline void upper_print(std::string& s) {
        upper_print_helper(s);
    }