Аргумент по умолчанию, gcc vs clang
Код выглядит так:
struct Foo {
Foo(const char *);
};
Foo::Foo(const char *str = 0)
{
}
VS 2013 и gcc 4.8.0 принимают такой код,
в то время как clang 3.3 отклоняет такой код с помощью:
ошибка: добавление аргумента по умолчанию в redeclaration делает этот конструктор конструктором по умолчанию
кто прав от стандартной (С++ 03 и С++ 11) точки зрения?
Примечание:
Мне нравится выбор clang, но я собираюсь сообщить об ошибке gcc и visual studio,
и если это неверно со стандартной точки зрения, это помогает
убедить разработчиков компиляторов исправить эту проблему.
НКУ
Я описал проблему здесь: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58194
Но не повезло, они приостанавливают исправление ошибок до тех пор, пока проект не станет стандартным.
Ответы
Ответ 1
Это обсуждалось в списке рассылки Clang и было представлено как Отчет о дефектах Основной выпуск 1344.
Из обсуждения в списке рассылки:
Идея состоит в том, что наличие определенных специальных элементов влияет на ядро свойства типа класса, например, будь то POD или тривиально копируемый. При решении этих свойств не требуется целая программа знание; для нас важно уметь выводить их из определение класса. Действительно проблематичным является обращение "нормальный" конструктор в конструктор копирования или перемещения, добавив значение по умолчанию аргументы, но IIRC, представляющий конструктор по умолчанию, также был проблематичным.
Исправление состоит в том, что вы должны поместить аргумент по умолчанию в начальный объявление конструктора.
В последний раз это обсуждалось РГ21 на совещании в Блумингтоне. Примечания от есть:
"Консенсус: сделайте это плохо сформированным, как было предложено в рецензии. выпуск 1344. Приоритет 0, подготовка Дуга."
Итак, CWG согласилась (в принципе), что это должно быть плохо сформировано.
TL; DR Clang прав, когда дефект фиксируется (не уверен, что это может официально произойти только с С++ 14, или если такие решения Комитета также могут быть сделаны ретроактивно на С++ 11)
Ответ 2
Я бы сказал, что КЛАНГ прав. В стандарте говорится (12.1.5 для старых и новых версий стандарта):
Конструктор по умолчанию для класса X является конструктором класса X, который можно вызывать без аргумента
Добавление значения по умолчанию к единственному аргументу конструктора, безусловно, позволяет вызывать его без аргументов, тем самым делая его по умолчанию. Кроме того, 8.3.6 говорит (акцент мой):
Выражение аргумента по умолчанию должно быть указано только в Параметр декларирование придаточного объявления <... >
Ответ 3
У вас есть декларация и определение. В вашей декларации вы не имеете значения по умолчанию, а в вашем определении - значение по умолчанию. Фактически подпись декларации очень похожа на подпись определения, но не то же самое. Я считаю, что строгость - хорошая идея, поэтому я считаю, что лучше обеспечить, чтобы объявление было таким же, как определение.