I have the following code, which I cannot get to work:
struct foo {};
foo foo1 = {};
template <foo& F>
class FooClass {};
template <foo& F>
void foobar(FooClass<F> arg) {
}
int main() {
FooClass<foo1> f;
foobar(f);
}
The error is:
main.cpp:14:5: error: no matching function for call to 'foobar'
note: candidate template ignored: substitution failure : deduced non-type template argument does not have the same type as the its corresponding template parameter ('foo' vs 'foo &')
Is it at all possible to infer lvalue reference template parameters? If so, how should it be done?
This is precisely covered by CWG 2091:
According to 14.8.2.5 [temp.deduct.type] paragraph 17,
If P
has a form that contains <i>
, and if the type of the corresponding value of A
differs from the type of i
, deduction
fails.
This gives the wrong result for an example like:
template<int &> struct X;
template<int &N> void f(X<N>&);
int n;
void g(X<n> &x) { f(x); }
Here, P
is X<N>
, which contains <i>
. The type of i
is int&
.
The corresponding value from A
is n
, which is a glvalue of type
int
. Presumably this should be valid.
I think this rule means to say something like,
If P
has a form that contains <i>
, and the type of i
differs from the type of the corresponding template parameter of the template
named by the enclosing simple-template-id, deduction fails.
As noted by @dyp, [temp.deduct.type]/17 should be more permissive. In your example, the argument in FooClass<F>
(F
) does not have reference type - it's an lvalue of type foo
. The template parameter of FooClass
is a reference. The DR was resolved last year.