Hello everyone,
template<typename X>
int mycall(const X& a)
{
std::cout << ">>> " << "int mycall(const X& a)" << std::endl;
return 0;
}
template<typename X>
int mycall(X&& a)
{
std::cout << ">>> " << "int mycall(X&& a)" << std::endl;
return 0;
}
template <typename T>
class CClass
{
public:
CClass(T t) : m_t{t}
{
}
template<typename U>
auto operator()(U&& t)
{
mycall(std::forward<U>(t));
}
private:
T m_t;
};
class A{};
int main()
{
CClass cc{5};
//1..
int x = 9;
cc(x);
cc(10);
cc(A{});
//4..
A a{};
cc(a);
return 0;
}
output:
>>> int mycall(X&& a)
>>> int mycall(X&& a)
>>> int mycall(X&& a)
>>> int mycall(X&& a)
In the example above, for the first and fourth calls, I initially expected that the universal reference would deduce as an lvalue reference, leading to the mycall(const T&) version being called due to perfect forwarding. However, I observed that the mycall(T&&) version is called instead.
When I removed the const qualifier, changing the function to mycall(T&), the first and fourth calls are forwarded as lvalue references, and as a result, the mycall(T&) version is called as expected. What is the effect of the const qualifier here? Why is the argument forwarded as an rvalue reference?
As mentioned in comments,
int mycall(X&& a)is also using a forwarding reference, hence it is prefered over the other template.Forwarding requires the template argument to be deduced, so one way to get the desired output is to not let it be deduced again:
Resulting output: