Why does the &&
argument type in the following example not behave as a so-called "universal reference" even though it seems to be in a "deduced context", and instead is interpreted as an r-value:
auto main() -> int {
using MyFn = void (*)(int &);
MyFn special = [](auto && thing) {}; // compile error, deduced as int && rather than int&
return 0;
}
Whereas the following, which I expect to be equivalent, does work?
template <typename T> void foo(T &&){};
auto main() -> int {
using MyFn = void (*)(int &);
MyFn specialC = foo;
return 0;
}
I suspect there's some esoteric detail with converting lambdas to function pointers that matters here, but so far I can't figure it out.
CodePudding user response:
Forwarding references are supported by a special deduction rule. The rule states that if we need to deduce T
in order to make T&&
identical to U&
, then T
is deduced as U&
(so that T&&
will be U& (&&)
, which just collapses down to U&
).
However, this special rule only applies under certain circumstances: when deducing function template template arguments based on the arguments to a function call ([temp.deduct.call]/3) (in the case that the argument is an lvalue of type U
, which you can imagine as having the type "U&
"), when taking the address of a function template, and when matching a function template specialization declaration against a primary template declaration ([temp.deduct.type]/10).
Your case is none of the above, but is instead a separate case of deducing template arguments for a conversion function template ([temp.deduct.conv]), which doesn't have the special rule for forwarding references.
Another example where the forwarding reference deduction rules don't apply is the following, which will therefore not compile:
template <class T>
void foo(void(*)(T&&)) {}
void bar(int&) {}
int main() {
foo(bar);
}
CodePudding user response:
In lambda parameters, auto
by itself gives universal type deduction. So this does what you want:
MyFn special = [](auto thing) {};
Demo using a non-copyable type to prove it's not passing by value: https://godbolt.org/z/5vfWc6c8x