#c
Вопрос:
Этот код не удается скомпилировать
template<unsigned n>
void test(char const (*)[n 1]) { }
int main()
{
char const arr[] = "Hi";
test(amp;arr);
}
с ошибкой
note: candidate template ignored: couldn't infer template argument 'n'
Однако, если вы измените n 1
на n
, он будет отлично компилироваться.
Почему компилятор не может сделать вывод n
, если к нему добавлено смещение?
Комментарии:
1. Но чего именно вы пытаетесь достичь, я не понимаю? Я имею в виду, что правила для совместимых типов требуют, чтобы размеры массива совпадали один к одному.
2. Как насчет мысленного упражнения? Что , если бы шаблон был указан как
void test(char const (*)[(n 3)*(n-2)])
, вы ожидали бы, что компилятор C выведетn
значение 9 при передаче массива из 84 символов?3. @SamVarshavchik: Нет, но это не значит, что он не мог справиться с базовым аффинным выражением.
Ответ №1:
Из ссылки cpp в разделе «Не выведенные контексты» :
В следующих случаях типы, шаблоны и значения, не относящиеся к типу, которые используются для создания P, не участвуют в выводе аргументов шаблона, а вместо этого используют аргументы шаблона, которые были выведены в другом месте или явно указаны. Если параметр шаблона используется только в не выводимых контекстах и явно не указан, вывод аргумента шаблона завершается ошибкой.
(…)
- Аргумент шаблона, не относящийся к типу, или массив, связанный, в котором подвыражение ссылается на параметр шаблона:
template<std::size_t N> void f(std::array<int, 2 * N> a);
std::array<int, 10> a;
f(a); // P = std::array<int, 2 * N>, A = std::array<int, 10>:
// 2 * N is non-deduced context, N cannot be deduced
// note: f(std::array<int, N> a) would be able to deduce N
(…)
В любом случае, если какая-либо часть имени типа не выводится, все имя типа не выводится из контекста. (…)
Поскольку n 1
это подвыражение, весь контекст тогда не может быть выведен.
Комментарии:
1. 1 спасибо. Но знаете ли вы
(n)
, должно ли это сработать тогда? Потому что он не работает на Clang, но работает на GCC и MSVC.2. @user541686 Я думаю, что Лязг прав.
(n)
следует сделатьn
подвыражение, которое должно сделать все это не выводимым контекстом. Это то, что также говорится в сообщении об ошибке Clang: «не удалось вывести аргумент шаблона …»