Passing a const lvalue reference as rvalue reference

676 views Asked by At

I have a function that accepts an rvalue reference:

template<typename... Ts>
void foo(std::tuple<Ts...>&& t)
{
    processFoo(std::forward<std::tuple<Ts...>>(t));
}

and another function that accepts an lvalue reference:

template<typename T>
void bar(const T& t);

I want bar to be able to bind with both lvalues and rvalues, so it's signature is OK. Then, I want to call foo with t from bar. For this code:

template<typename T>
void bar(const T& t);
{
    foo(t);
}

my compiler rightfully complains that there is no matching function for call to foo(...), as std::tuple<_blahblahblah> and const std::tuple<_blah> have incompatible cv-qualifiers. So I do the following:

template<typename T>
void bar(const T& t);
{
    foo(std::forward<T>(const_cast<T&>(t)));
}

but the const_cast looks like a workaround!

Does the above forwarding code look OK and idiomatic? Maybe it would be better to overload foo for other reference types and cv-qualifiers? Or is there any "even more universal" reference, which would help to get rid of const_cast?

1

There are 1 answers

1
Holt On BEST ANSWER

This cannot work before std::tuple<Ts...> && is not a forwarding reference, it is a simple rvalue-reference, and you cannot bind a const lvalue-ref to a rvalue-ref - Change your code to:

template<typename Tuple>
void foo(Tuple&& t) {
    processFoo(std::forward<Tuple>(t));
}

And you will have a real forwarding reference, and your code will work.