аргумент по умолчанию, gcc vs clang

Код выглядит так:

struct Foo { Foo(const char *); }; Foo::Foo(const char *str = 0) { } 

VS 2013 и gcc 4.8.0 принимают такой код, в то время как clang 3.3 отклоняет такой код:

Ошибка: добавление аргумента по умолчанию в redeclaration делает этот конструктор конструктором по умолчанию

кто прав со стандартной (C ++ 03 и C ++ 11) точки зрения?

Замечания:

Мне также нравится выбор клана, но я собираюсь сообщить об ошибке в gcc и visual studio, и если это не правильно со стандартной точки зрения, это помогает убедить разработчиков компилятора исправить эту проблему.

НКУ

Я описал проблему здесь: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58194

Но не повезло, они приостанавливают исправление ошибок до того, как проект станет стандартным.

Это обсуждалось в списке рассылки Clang и было представлено в качестве основного отчета об ошибках 1344.

Из обсуждения в списке рассылки:

Идея состоит в том, что присутствие определенных специальных элементов влияет на основные свойства типа classа, например, будь то POD или тривиально с возможностью копирования. При решении этих свойств не требуется знание всей программы; для нас важно иметь возможность выводить их только из определения classа. В самом деле проблемный случай превращает «нормальный» конструктор в конструктор копирования или перемещения, добавляя аргументы по умолчанию, но IIRC, представляющий конструктор по умолчанию, также был проблематичным.

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

В последний раз это обсуждалось РГ21 на совещании в Блумингтоне. Заметки оттуда:

«Консенсус: сделайте это плохо сформированным, как было предложено в рецензии. Основная проблема 1344. Приоритет 0, составление Дуга».

Поэтому КГВ согласилась (в принципе), что это должно быть плохо сформировано.

TL; DR Clang прав, когда дефект фиксируется (не уверен, что это может официально произойти только с C ++ 14, или если такие решения Комитета также могут быть сделаны ретроактивно на C ++ 11)

Я бы сказал, что КЛАНГ прав. В стандарте говорится (12.1.5 для старых и новых версий стандарта):

Конструктор по умолчанию для classа X является конструктором classа X, который можно вызывать без аргумента

Добавление значения по умолчанию к единственному аргументу конструктора, безусловно, позволяет вызывать его без аргументов, тем самым делая его по умолчанию. Кроме того, 8.3.6 говорит (основное внимание):

Выражение аргумента по умолчанию должно указываться только в объявлении параметра-объявления объявления функции <...>

У вас есть декларация и определение. В вашей декларации вы не имеете значения по умолчанию, а в вашем определении – значение по умолчанию. Фактически подпись декларации очень похожа на подпись определения, но не то же самое. Я считаю, что строгость – хорошая идея, поэтому я считаю, что лучше обеспечить, чтобы декларация была такой же, как определение.