3

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?

Sergey
  • 7,985
  • 4
  • 48
  • 80
  • 2
    `foo` doesn't modify its parameter or take ownership of it. Declare it as accepting a `const` reference as well. I see no reason to accept a forwarding reference here. – StoryTeller - Unslander Monica Dec 19 '16 at 08:15
  • 1
    `std::tuple&& t` is not a forwarding reference. – Holt Dec 19 '16 at 08:21
  • @StoryTeller in real code it performs forwarding, so I need rvalue reference. I modified the code example. – Sergey Dec 19 '16 at 08:23
  • 1
    Well, as Hold pointed out and I missed, this isn't a forwarding reference at all. Just a regular rvalue reference to a `std::tuple`. So again, just go with `const`, or drop it entirely. You aren't actually doing any forwarding. – StoryTeller - Unslander Monica Dec 19 '16 at 08:28

1 Answers1

5

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.

Holt
  • 36,600
  • 7
  • 92
  • 139