Редактировать:
По-видимому, GCC позволяет создать экземпляр шаблона класса без списка параметров (когда параметры заданы по умолчанию), что не соответствует требованиям (соответствует требованиям Clang) .
Я предполагаю, что причина, по которой требуются скобки (даже если список параметров пуст), заключается в том, чтобы явно указать, что это экземпляр шаблона, а не фактический тип.
Итак, я задаю свой исходный вопрос о различиях между случаями шаблона класса и шаблона функции: почему во втором фрагменте разрешено вызывать a без скобок, в отличие от экземпляра A в первом фрагменте? А почему это не разрешено для b?
template<int i = 1>
struct A {
operator int() { return i; }
};
template<int i = 2>
using B = A<i>;
// using C = A; <-- error: missing template arguments after 'A'
using C = A<>;
int main() {
A a; // Edit: Actually should require brackets: A<> a;
// B b; <-- error: missing template arguments before 'b'
B<> b;
C c;
}
Я попытался создать аналогичный сценарий с шаблоном функции вместо шаблона класса, и в последнем случае (C) есть небольшая разница: список параметров не требуется, если тип возвращаемого значения указан в определении a. Думаю, я понимаю почему, но я хотел бы получить некоторые идеи. В остальном оба случая аналогичны шаблонным классам.
template<int i = 1>
auto a() { return i; }
// auto a() -> int { return i; }
// if the return type is specified, c can be defined as commented below
template<int i = 2>
auto b = a<i>;
// auto c = a; <-- error: unable to deduce 'auto' from 'a'
auto c = a<>;
int main() {
a();
// b(); <-- error: missing template arguments before '(' token
b<>();
c();
}
Кроме того, есть ли существенные различия между современными стандартами C++ (от C++ 11 до C++ 20)? Меня больше всего интересует случай C++ 17, но я хотел бы знать, изменились ли эти вещи или собираются ли они. Из того, что я видел, в C++ 14 для создания экземпляра шаблона класса в любом случае требуется список параметров, а для вызова шаблона функции - нет. И я не нашел различий между C++ 17 и C++ 2a с GCC.
@cpplearner Я не совсем понимаю, на какую часть это должно повлиять. Clang кажется мне послушным?
Какой clang, clang 5.0.0 или clang 7.0.0 (что позволяет использовать A a;)?
@cpplearner О, значит, Clang 7.0.0 допускает то же самое, что и GCC, что не соответствует требованиям? Это просто то, что оба компилятора добавили для удобства, или это ошибка в обоих? Или это действительно допускается стандартом?





Аргументы шаблона [temp.arg] / 4 (§12.3 / 4)
When template argument packs or default template-arguments are used, a template-argument list can be empty. In that case the empty
<>brackets shall still be used as the template-argument-list.
Такая же формулировка для C++ 17 в §17.3 / 4, для C++ 14 и C++ 11 в §14.3 / 4.
Явная спецификация аргумента шаблона [temp.arg.explicit] (§12.9.1 / 3):
If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list
<>itself may also be omitted.
Такая же формулировка для C++ 17 в §17.8.1 / 3, для C++ 14 и C++ 11 в §14.8.1 / 3.
Ваш
template<int i = 2> auto b = a<i>;
- это шаблон переменных, для которого не выполняется вывод аргументов.
Так это «ошибка» GCC, позволяющая опустить скобки? А как насчет случая шаблона функции?
Хорошо, это действительно похоже на ошибку с GCC, поскольку Clang не допускает ее в случае шаблона класса. Однако это касается шаблонов функций. Есть ли причина такой разницы?
Может быть, добавьте еще один простой пример того, что позволяет clang и о чем вы беспокоитесь в своем вопросе? Кстати. Вы в курсе, что auto c = a<>; определяет указатель функции a?
Я знаю, что c - указатель на функцию (как и b). Есть что-нибудь ближе к псевдониму для функций?
@Nelfeal Не совсем. Просто попросил убедиться. Однако ваш b - это шаблон переменной.
Итак, если я правильно понимаю, разница на самом деле заключается между тремя случаями: шаблонами классов, шаблонами функций и шаблонами переменных. И по какой-то причине экземпляры шаблонов функций - единственные, которые не требуют скобок при выводе аргументов. А если есть значения по умолчанию, то аргументы действительно выводятся. Это верно?
@Nelfeal AFAICT Да.
Coliru использует немного устаревший clang (5.0.0, последняя версия - 7.0.0), который не реализует некоторые отчеты о дефектах, касающиеся CTAD.