Search code examples
c++referencelanguage-lawyerreference-collapsing

when will there be && + && -> && with c++ reference collapse?


I have some question about understanding reference collapse, so I do experiments in the following code:

template<typename T>
void func(T&& t) {}


int main() {
    // There is no reference collapse here, only binding left or right values to
    // references with universal reference:
    int a = 10;
    func(a); // this equals func<int>(a)
    func(10); // what does this equal to?
    func(std::move(a)); // what does this equal to?

    // The following is not case of universal reference, they are reference
    // collapse, only that the type is template type:
    int& b1 = a;
    int&& b2 = 10;

    // this is the collapse of & + && -> &
    func(b1); // this equals func<int&>(b1)

    // this is the collapse of & + && -> &, since b2 is left reference here not
    // right reference:
    func(b2); // this equals func<int&&>(b2)
}

Am I correct on understanding the above code? Would you please show me the case of collapsing && + && -> && ?


Solution

  • You have some misunderstanding with forwarding reference. When being passed lvalues to func, the template parameter T will be deduced as lvalue-reference; for rvalues T will be deduced as non-reference type. I.e.

    int a = 10;
    func(a);  // T is deduced as int&, then int& && -> int& is the type of parameter t
    func(10); // T is deduced as int, then int&& is the type of parameter t
    func(std::move(a)); // T is deduced as int, then int&& is the type of parameter t
    
    int& b1 = a;
    int&& b2 = 10;
    func(b1); // T is deduced as int&, then int& && -> int& is the type of parameter t
    func(b2); // T is deduced as int&, then int& && -> int& is the type of parameter t. Note that b2 is an lvalue
    

    Would you please show me the case of collapsing && + && -> && ?

    You can

    func<int&&>(0); // T is specified as int&&, then int&& && -> int&& is the type of parameter t