Search code examples
c++templatesrvalue-referencepass-by-rvalue-reference

Templates and using rvalues references as a parameter


So I have a std::map< std::string, boost::any > called OptionsMap and I want to create a function that takes any type (therefore the template) and stores it in the map. Would the next code work?

template <typename T>
void Set(std::string optionName, T&& optionValue)
{
    OptionsMap[optionName] = optionValue;
}

Solution

  • Typically, when a function template accepts a universal reference (i.e. an rvalue reference of a deduced type), you should cast the function parameter with forward so as to obtain a value of the same value category as was provided by the argument in the function call:

    template <typename T>
    void Set(std::string optionName, T&& optionValue)
    {
        OptionsMap[optionName] = std::forward<T>(optionValue);
        //                       ^^^^^^^^^^^^^^^
    }
    

    The parameter variable optionValue itself is always an lvalue, so without the cast, you would be making copies of what should be moves. If the type is copyable, this will be less efficient than expected; if the type isn't copyable (e.g. unique_ptr), it's worse: your function now accepts an argument that it will subsequently fail to compile with.