Вывод аргумента шаблона шаблона не работает с шаблоном псевдонима
рассмотрите приведенный ниже код. Я определил очень простой класс, для которого компилятор генерирует неявный указатель вывода, поэтому его можно построить без явных аргументов шаблона. Однако вывод аргумента шаблона не работает для построения объекта из простого шаблона псевдонима, который только пересылается непосредственно в целевой класс:
template< typename A, typename B >
struct Foo {
Foo( A const &a, B const &b )
: a_(a), b_(b)
{ }
A a_;
B b_;
};
template< typename A, typename B >
using Bar = Foo<A, B>;
auto foobar() {
Foo r{1, 2};
Bar s{3, 4};
// ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
// ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
// Bar s{3, 4};
// ^
return 1;
}
Как вы можете видеть из комментария кода выше, g++ дает мне ошибку об использовании шаблона с псевдонимом без шаблонных аргументов. Я надеялся в таком случае, что вывод аргумента шаблона будет перенаправлен.
Итак, мой вопрос: Является ли это экспресс-дизайном текущей формулировки предложения для вывода аргумента шаблона шаблона? Или это незавершенная функция или ошибка в текущей реализации функции g++? И это будет скорее вопросом для авторов предложения, или для Комитета по ИСО С++, но если кто-нибудь из них увидит это: было бы желательно, чтобы окончательная формулировка этой функции включала включение шаблонов псевдонимов, таких как это, также имеют неявные направляющие, сгенерированные для них?
Я могу понять, что поскольку шаблоны псевдонимов могут иметь любые параметры шаблона, не всегда возможно, чтобы компилятор успешно выводил аргументы шаблона целевого класса, но в таком случае я ожидал бы, что компилятор сможет таким же образом, что он может непосредственно для целевого класса.
Я создаю gcc, созданный из головы всего несколько дней назад, используя --std=c++1z
. Полная информация о версии: gcc version 7.0.0 20161201 (experimental) (Homebrew gcc HEAD- --with-jit)
Ответы
Ответ 1
Это была функция, которую мы рассматривали при формулировании предложения, но она была в конечном итоге сокращена, потому что у нас еще не было достаточно хорошего дизайна для нее. В частности, есть некоторые тонкости в отношении того, как вы выбираете и преобразуете направляющие выводов из шаблона с псевдонимом в направляющие выводов для шаблона псевдонимов. Существуют также открытые вопросы о том, как вести себя, если шаблон псевдонима не является простым псевдонимом для другого шаблона. Некоторые примеры:
template<typename T> struct Q { Q(T); }; // #1
template<typename T> struct Q<T*> { Q(T); }; // #2
template<typename T> using QP = Q<T*>;
int *x;
Q p = x; // deduces Q<int*> using #1, ill-formed
QP q = x; // deduces Q<int*> using #1, or
// deduces Q<int**> using #2?
template<typename T> Q(T) -> Q<T>; // #3
QP r = x; // can we use deduction guide #3 here?
template<typename T> Q(T*) -> Q<T**>; // #4
int **y;
QP s = y; // can we use deduction guide #4 here?
template<typename T> struct A { typedef T type; struct Y {}; };
template<typename T> using X = typename A<T>::type;
template<typename T> using Y = typename A<T>::Y;
X x = 4; // can this deduce T == int?
X y = A<int>::Y(); // can this deduce T == int?
Есть достойные ответы на вышеупомянутые вопросы, но их устранение добавляет сложности, и было бы предпочтительнее запретить вывод для шаблонов псевдонимов для С++ 17, а не торопить что-то изъявленное.
Я предскажу, что мы увидим документ от Faisal, предлагающий эту функцию для С++ 20.
Ответ 2
Из http://en.cppreference.com/w/cpp/language/template_argument_deduction, "Шаблоны псевдонимов никогда не выводятся". Итак, это по дизайну.