Можно ли вывести параметр ссылочного шаблона без значения типа lvalue?

У меня есть следующий код, с которым я не могу работать:

struct foo {};
foo foo1 = {};

template <foo& F>
class FooClass {};

template <foo& F>
void foobar(FooClass<F> arg) {
}

int main() {
    FooClass<foo1> f;
    foobar(f);
}

Ошибка:

main.cpp: 14: 5: ошибка: нет соответствующей функции для вызова foobar

note: шаблон-кандидат игнорируется: сбой замены: выведенный аргумент шаблона не-типа не имеет того же типа, что и соответствующий ему параметр шаблона ('foo' vs 'foo &')

Возможно ли выводить параметры шаблона ссылочного значения lvalue? Если да, то как это сделать?

Ответ 1

Это точно описано CWG 2091:

В соответствии с пунктом 14.8.2.5 [temp.deduct.type] 17,

Если P имеет форму, содержащую <i>, и если тип соответствующего значения A отличается от типа i, то вывод   выходит из строя.

Это дает неверный результат для примера, например:

template<int &> struct X;
template<int &N> void f(X<N>&);
int n;
void g(X<n> &x) { f(x); }

Здесь P есть X<N>, который содержит <i>. Тип i равен int&. Соответствующее значение из A равно n, которое является значением gl типа int. Предположительно это должно быть действительно.

Я думаю, что это правило означает сказать что-то вроде

Если P имеет форму, содержащую <i>, а тип i отличается от типа соответствующего шаблонного параметра шаблона   названный вложенным идентификатором simple-template-id, вывод не выполняется.

Как отмечено @dyp, [temp.deduct.type]/17 должно быть более разрешительным. В вашем примере аргумент в FooClass<F> (F) не имеет ссылочного типа - это значение l типа типа foo. Параметр шаблона FooClass является ссылкой. DR был разрешен в прошлом году.