Почему параметры по умолчанию не работают вместе с пакетом параметров? - PullRequest
0 голосов
/ 10 января 2020

Из-за 8.3.6 ([dcl.fct.default]) / 4 ,

В данном объявлении функции каждый параметр, следующий за параметром со значением по умолчанию Аргумент должен иметь аргумент по умолчанию, предоставленный в этом или предыдущем объявлении, или должен быть пакетом параметров функции.

следующее должно компилироваться:

#include <iostream>

template<typename ...Ts>
void foo(int i=8, Ts... args)
{
    std::cout << "Default parameters \t= " << i << "\n";
    std::cout << "Additional params  \t= " << sizeof...(Ts) << "\n";
}

int main()
{
    foo();                  // calls foo<>(int)
    foo(1, "str1", "str2"); // calls foo<const char*, const char*>(int, const char*, const char*)
    foo("str3");            // ERROR: does not call foo<const char*>(int, const char*)

    return 0;
}

Но оно не компилируется из-за на foo("str3"), что смущает компилятор. Он жалуется, что не существует соответствующей функции для вызова foo(const char*) и что он не может преобразовать "str3" (тип const char*) в тип int.

Я понимаю, что можно обойти эту проблему, прибегают к перегрузке функции или используют именованный параметр-идиому (ср. , где поместить параметр значения по умолчанию в функцию переменной длины в c ++? и аргументы по умолчанию и variadi c функции ). Однако я хотел бы знать, является ли компилятор просто глупым или есть подлинная причина, почему предполагаемое поведение в приведенном выше примере кода не реализовано. Другими словами, почему компилятор жалуется, даже если я явно создаю экземпляр функции как foo<const char*>(int, const char*)? Это как если бы явная реализация просто игнорировала значение параметра по умолчанию. Почему?

Ответы [ 3 ]

5 голосов
/ 10 января 2020

Стандарт, который вы цитируете, просто говорит, что допустимо формировать

template<typename ...Ts>
void foo(int i=8, Ts... args)

Когда вы его вызываете, вам все равно придется передать int в качестве первого параметра, иначе функция не будет учитываться при разрешении перегрузки. Когда вы делаете

foo("str3");

, компилятор будет искать любую функцию foo, которая принимает const char* или const char(&)[5], поскольку это единственный параметр. Это означает, что ваша функция полностью игнорируется, поскольку она ожидает и int для первого параметра или вообще не имеет параметров.

5 голосов
/ 10 января 2020

Параметры со значениями по умолчанию остаются позиционными. Ваш пример такой же как

void foo(int i=8, const char * c="hello world")
{
    std::cout << "Default param \t= " << i << "\n";
    std::cout << "Additional param \t= " << c << "\n";
}

int main()
{
    foo();                  // 8 "hello world"
    foo(1, "str1");         // 1 "str1"
    foo("str3");            // ERROR: parameter mismatch

    return 0;
}
3 голосов
/ 10 января 2020

Это не работает по тем же причинам, по которым это не будет работать:

void f(int = 0, const char*);

int main() {
    f("test")
}

Если вы прочитаете ошибку, вы увидите, что компилятор не может преобразовать строковый литерал в int. И это действительно так, первый параметр является целым числом, и вы отправили ему строковый литерал.

Параметры не могут быть восстановлены в другую позицию, независимо от того, есть ли аргумент по умолчанию или нет.

...