Не выведенный контекст для не типового параметра - PullRequest
0 голосов
/ 15 декабря 2018

Я читаю Шаблоны C ++ (2-е издание), и это фрагмент из книги:

template<typename... Ts, int N>
void f(double (&)[N+1], Ts... ps) {return;}

В книге указано, что приведенное выше объявление бесполезно, поскольку N не может быть указано или выведено.

Я пытаюсь понять, почему что-то вроде следующего является ошибкой:

double arr[2];
f<int, double, 1>(arr, 1, 2.0);

Когда я компилирую фрагмент выше, я получаю сообщение об ошибке, что не существует соответствующей функции для вызова f,

Это прекрасно компилируется

template<typename... Ts, typename T> 

void func(T value){}; 
func(1); 

, хотя у меня есть дополнительный параметр после пакета параметров.

Почему мое указание аргументов шаблона явно не соответствует предоставленным аргументам?Пожалуйста, помогите мне понять это.

1 Ответ

0 голосов
/ 15 декабря 2018

Тот факт, что N не может быть выведен, не имеет ничего общего с пакетом параметров.Это также не компилируется, потому что невозможно вывести N.

template<int N>
void f(double (&)[N+1]) {}

int main() {
    double arr[2];
    f(arr);
}

Из cppreference (Неведуемые контексты):

В следующих случаях:типы, шаблоны и нетипизированные значения, которые используются для составления P, не участвуют в выводе аргументов шаблона, а вместо этого используют аргументы шаблона, которые были либо выведены в другом месте, либо явно указаны.Если параметр шаблона используется только в не выведенных контекстах и ​​не указан явно, вывод аргумента шаблона завершается неудачей.
[...]
3) Нетипичный аргумент шаблона или массив, связанный с подвыражениемссылается на параметр шаблона

Тот факт, что N не может быть указан, имеет другую причину: в стандарте говорится, что вы просто не можете указать параметр, помещенный после пакета параметров.

From [temp.param]:

За пакетом параметров шаблона шаблона функции не должен следовать другой параметр шаблона, если только этот параметр шаблона не может быть выведен из списка типов-параметров изшаблон функции или имеет аргумент по умолчанию (14.8.2). [Пример:

template<class T1 = int, class T2> class B;    // error

// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { }  // error
template<class... T, class U> void g() { }     // error

- конец примера]

(см. этот вопрос , из которого яполучил цитату)

Ваш другой пример работает, потому что T можно вывести из параметров.

template<typename... Ts, typename T> 
void func(T value){}; 
func(1); // 1 is used to deduce T
...