Search code examples
c++c++20rvalue-reference

Do rvalues decay silently?


std::vector foo( std::vector && rval )
{
    return std::move( rval );
}

If a function expects an rvalue reference but gets something else - e.g. a const reference or a temporary or whatever different from std::move(vec), will it silently make a copy instead of throwing an error or even a warning?


Solution

  • Try it yourself:

    #include <iostream>
    
    struct S {
        S() { }
        S(const S& other) { std::cout << "copy ctor" << std::endl; }
        S(S&& other) { std::cout << "move ctor" << std::endl; }
    }; 
    
    int foo( S && rval )
    {
        return 1;
    }
    
    int main()
    {
        S s1;
        foo (s1);
    }
    

    Copying S'es is not silent. So, what happens when you try to compile this?

    This happens (Godbolt):

    <source>: In function 'int main()':
    <source>:17:10: error: cannot bind rvalue reference of type 'S&&' to lvalue of type 'S'
       17 |     foo (s1);
          |          ^~
    <source>:9:15: note:   initializing argument 1 of 'int foo(S&&)'
        9 | int foo( S && rval )
          |          ~~~~~^~~~
    

    So, the answer to your question is "no".