1

Trying to use rightvalues a bit more but I got confused, how should I design my function in which I want to use the right value:

// Pass by whatever-it's-called
void RockyBalboa::DoSomething(std::string&& str){ 
     m_fighters.push_back(str);
}
// Pass by reference
void RockyBalboa::DoSomething(std::string& str){
     m_fighters.push_back(std::move(str)); 
}

And what is effectively the difference between these two function calls? And what happens when I pass it with double ampersand and use std::move ?

dejoma
  • 394
  • 1
  • 6
  • 18

1 Answers1

3

You've swapped the usage. It's the Rvalue reference that can be moved. The Lvalue reference should be made const:

// Rvalue reference
void RockyBalboa::DoSomething(std::string&& str){ 
     m_fighters.push_back(std::move(str));
}
// Lvalue reference
void RockyBalboa::DoSomething(const std::string& str){ // note: const
     m_fighters.push_back(str);
}

You could however use a forwarding reference to cover both cases:

#include <type_traits>

// Forwarding reference
template<typename T>
void RockyBalboa::DoSomething(T&& str) {
    // Create a nice error message at compile time if the wrong type (T) is used:
    static_assert(std::is_convertible_v<T, std::string>);

    m_fighters.emplace_back(std::forward<T>(str));
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Awesome, I actually needed forward too because I have a wrapper function that does something like `wrapper(std::string&& str) { return g(std::string str) }` which I now changed to `return g(std::forward(str))` – dejoma Aug 25 '20 at 11:12
  • @dejoma Glad it helped! Please do read the link about forwarding references carefully - especially the part that says: "_Forwarding references are either: 1) function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template. 2) `auto&&` except when deduced from a brace-enclosed initializer list:_". – Ted Lyngmo Aug 25 '20 at 11:17