Наследование конструктора и предоставление новой перегрузки: базовый конструктор без аргументов, похоже, не участвует в разрешении перегрузки

Тесты показывают странное поведение (c++14, g++ 4.9.1, clang 3.5.5):

Подвести итог:

  • если B не предоставляет других конструкторов, он может использовать A::A()
  • если B предоставляет другие конструкторы, он не может использовать A::A(), но использует A::A(whatever arguments), что является неожиданным поведением (по крайней мере, для меня).

Настройка 1:

struct A {
  A() {};
  A(int) {}; // with or without this overload the result are the same
};

struct B : A {
  using A::A;
};

B b0{}; // OK

Настройка 2:

struct A {
  A() {}; // with a default constructor instead (empty class A)
          // the results are the same
};

struct B : A {
  using A::A;
  B(int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK

Настройка 3:

struct A {
  A() {};
  A(int) {};
};

struct B : A {
  using A::A;
  B(int, int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK
B b2{24, 42}; // OK

Почему это происходит и как это можно "исправить".


person bolov    schedule 24.02.2015    source источник
comment
Конструктор по умолчанию особенный. Вы можете исправить это, например. написав явное объявление конструктора по умолчанию и установив его по умолчанию: B() = default; Я предполагаю, что некоторые свойства конструктора по умолчанию не могут быть воспроизведены наследующим конструктором, например тривиальность, отсюда и специальные правила.   -  person dyp    schedule 24.02.2015
comment
Это именно те примеры, с которыми вы строите, они не работают или я? Можете дать живую ссылку? то есть wandbox или Coliru   -  person Shafik Yaghmour    schedule 24.02.2015
comment
@dyp Вы правы. Почему бы не поместить свой комментарий в ответ? ;)   -  person Daniel Frey    schedule 24.02.2015
comment
Примеры не должны быть реальными. Во-первых, вы ничего не наследуете. Создайте MCVE.   -  person    schedule 24.02.2015
comment
sry, набрал вместо копирования, исправил наследование.   -  person bolov    schedule 24.02.2015
comment
@DanielFrey Потому что я не совсем уверен в обосновании. Перечитывая предложение, кажется, что между правилами наследования ctors и неявной генерацией ctors существует некое нетривиальное взаимодействие. Это также может быть причиной исключений (нет по умолчанию, копировать, перемещать ctor через наследование ctor).   -  person dyp    schedule 24.02.2015
comment
Вместо того, чтобы результат был одинаковым, укажите в тестовом примере, что именно происходит, чего вы не хотите (или наоборот). Ваш вопрос сложно разобрать.   -  person Lightness Races in Orbit    schedule 24.02.2015
comment
@DanielFrey Кроме того, дубликаты. stackoverflow.com/q/20435859 и т. д.   -  person dyp    schedule 24.02.2015
comment
bolov, печатать — это хорошо (вам все равно нужно исправить форматирование), но затем скопируйте обратно и проверьте свой код.   -  person Yakk - Adam Nevraumont    schedule 24.02.2015
comment
@LightnessRacesinOrbit Часть OP, как это можно исправить, возможно, делает это отдельным вопросом, нет? (По крайней мере, вы могли бы добавить это к своему ответу :)) -- редактировать: ой, вы это сделали. также: xkcd.com/541   -  person dyp    schedule 24.02.2015


Ответы (1)


Я не могу объяснить вам причину этого, но я могу, по крайней мере, сказать вам, что это предписано стандартом:

[C++11: 12.9/3]: для каждого конструктора, не являющегося шаблоном, в наборе кандидатов унаследованных конструкторов, кроме конструктора без параметров или конструктора копирования/перемещения с одним параметром, неявно объявляется конструктор с теми же характеристиками конструктора. если в классе, где появляется декларация использования, нет объявленного пользователем конструктора с той же сигнатурой. [..]

Поскольку B() по умолчанию вызывает A() по умолчанию, вы можете "исправить" это следующим образом:

struct B : A
{
   B() = default;

   using A::A;
   B(int, int){}
};

(демонстрация)

Следующая формулировка исходного предложения (n2540) предполагает, что простота и симметричность этого исправления являются более или менее движущими факторами, стоящими за решением, хотя я все еще нахожу это несколько неудовлетворительным. Ну что ж.

Конструкторы копирования и конструкторы по умолчанию не перенаправляются в соответствии с существующими правилами неявного объявления конструкторов копирования/по умолчанию.

person Lightness Races in Orbit    schedule 24.02.2015