Аргумент по умолчанию в середине списка параметров? - PullRequest
52 голосов
/ 12 апреля 2011

Я видел объявление функции в нашем коде, которое выглядело следующим образом

void error(char const *msg, bool showKind = true, bool exit);

Сначала я подумал, что это ошибка, потому что вы не можете иметь аргументы по умолчанию в середине функций, но компилятор принял это объявление,Кто-нибудь видел это раньше?Я использую GCC4.5.Это расширение GCC?

Странно то, что если я возьму это в отдельный файл и попытаюсь скомпилировать, GCC отклонит его.Я дважды проверил все, включая используемые параметры компилятора.

Ответы [ 2 ]

57 голосов
/ 12 апреля 2011

Этот код будет работать, если в самом первом объявлении функции последний параметр имеет значение по умолчанию, что-то вроде этого:

//declaration
void error(char const *msg, bool showKind, bool exit = false);

А затем в той же области действия вы можете указать значения по умолчанию для других аргументов (с правой стороны) в более позднем объявлении, как:

void error(char const *msg, bool showKind = true, bool exit); //okay

//void error(char const *msg = 0 , bool showKind, bool exit); // error

который может называться:

error("some error messsage");
error("some error messsage", false);
error("some error messsage", false, true);

Онлайн-демонстрация: http://ideone.com/aFpUn

Обратите внимание, что если вы укажете значение по умолчанию для первого параметра (слева) без указания значения по умолчанию для второго, оно не будет скомпилировано (как и ожидалось): http://ideone.com/5hj46


§8.3.6 / 4 говорит,

По умолчанию для не шаблонных функций аргументы могут быть добавлены позже объявления функции в том же Объем.

Пример из самого стандарта:

void f(int, int);
void f(int, int = 7);

Второе объявление добавляет значение по умолчанию!

Также см. §8.3.6 / 6.

8 голосов
/ 12 апреля 2011

Ответ может быть в 8.3.6:

8.3.6 Аргументы по умолчанию

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

Пример:

class C {
void f(int i = 3);
void g(int i, int j = 99);
};
void C::f(int i = 3) // error: default argument already
{ } // specified in class scope
void C::g(int i = 88, int j) // in this translation unit,
{ } // C::g can be called with no argument

Прочитав это, я обнаружил, что MSVC10 принимает следующее с отключенными расширениями компилятора:

void error(char const* msg, bool showKind, bool exit = false);

void error(char const* msg, bool showKind = false, bool exit)
{
    msg;
    showKind;
    exit;
}

int main()
{
    error("hello");
}
...