Ответ 1
Это похоже на ошибку gcc
. Я сообщил об этом как о проблеме # 80242.
gcc
жалуется на достоверность i
как аргумент шаблона:
ошибка: аргумент шаблона 1 недействителен
Я следил за грамматикой С++ из trailing-return-type
до template-argument
, который должен быть constant-expression
:
шаблон аргументов:
- константа-выражение < -
- тип-идентификатор
- ID-выражение
Тогда возникает реальный вопрос: "i
действительный constant-expression
?" .
Я думаю, что ответ "да" , потому что §8.20.4 [выражение. Const] говорит:
Преобразованное константное выражение типа
T
представляет собой выражение, неявно преобразованное в типT
, где преобразованное выражение является константным выражением, а последовательность неявного преобразования содержит только:
- пользовательские преобразования,
[...]
(Примечание. Такие выражения могут использоваться в новых выражениях, как выражения case, как инициализаторы перечисления, если базовый тип фиксирован, как границы массива, и как аргументы шаблона непигового типа.)
Существует последовательность неявных преобразований, которая, начиная с i
, будет вызывать преобразованное константное выражение, которое является постоянным выражением. Дано:
template <int>
struct bar { };
template <class I>
auto foo(I i) -> bar<i> { }
int main()
{
foo(std::integral_constant<int, 1>{}); // (0)
}
-
В контексте вызова функции в (0) аргумент
i
является экземпляромstd::integral_constant<int, 1>
. -
std::integral_constant
предоставляетconstexpr
пользовательское преобразование в базовыйvalue_type
. -
Преобразованные выражения констант явно разрешают пользовательские преобразования, как показано выше в §8.20.4 [выражение. Const].
-
std::integral_constant::operator value_type()
вернет аргумент шаблона non-type1
. Это основное постоянное выражение, поскольку оно не нарушает ни одно из правил, указанных в §8.20.2 [expr.const]. -
Следовательно, преобразованное константное выражение является константным выражением.