Distinguishing r- and l-value references as template arguments

Viewed 78

Let's consider the following example:

void f(int&& i)
{ }

template <typename ... X, typename ... Y>
void g(void(*p)(X&&..., Y&...))
{ }

int main()
{
    g(f);
    return 0;
}

Compilation fails with error

<source>:10:7: error: invalid conversion from 'void (*)(int&&)' to 'void (*)(int&)' [-fpermissive]
   10 |     g(f);
      |       ^
      |       |
      |       void (*)(int&&)
<source>:5:14: note:   initializing argument 1 of 'void g(void (*)(X&& ..., Y& ...)) [with X = {}; Y = {int}]'
    5 | void g(void(*p)(X&&..., Y&...))
      |        ~~~~~~^~~~~~~~~~~~~~~~~

Demo on godbolt.

Apparently on deducing the template arguments all the function arguments produce ordinary l-value references while the set of r-value references remains empty (contrasting my own expectations) – but why?

Side note: The problem that originally led to this question is solved by other means (recursive variadic template function producing a tuple) in the meanwhile, thus no XY-problem; asking out of curiosity – still would appreciate any other elegant solution which does not involve introducing tuples to the functions in question (f in above example).

0 Answers
Related