Search code examples
c++perfect-forwardingtype-deductionforwarding-reference

c++ perfect forwarding with universal reference prevents type deduction?


I consider the following 2 snippets which do the same thing. In the first case, I don't use a universal reference, and so I have to write the function set twice. In the second case, with a universal reference I can write the function once, but the user of the class has to specify explicitly the type passed to the function set. Is there a trick to get both advantages?

#include <iostream>

struct A {};

template<typename T>
struct B {

    void set(const A& a) {
        a_=a;
    }
    
    void set(A&& a) {
        a_=std::forward<A>(a);
    }

    A a_;
};

int main() {

    B<A> b;
    A a;

    b.set({});
    b.set(a);

    return 0;
}

and

#include <iostream>

struct A {};

template<typename T>
struct B {

    template<typename U>
    void set(U&& a) {
        a_=std::forward<U>(a);
    }
    
    A a_;
};

int main() {

    B<A> b;
    A a;

    b.set(A{}); // here I can't do b.set({}) because the template parameter U would be undefined
    b.set(a);

    return 0;
}

Solution

  • In this case, you can add a default value to the U template parameter like

    template<typename U = T>
    void set(U&& a) {
        a_=std::forward<U>(a);
    }
    

    and now if it can deduce the type, like with {} which has no type, then it will fall back t using T as the type for U.