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

Тесты показывают странное поведение (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

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

1 ответ

Решение

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

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

Так как по умолчанию B() вызывает по умолчанию A() Вы можете "исправить" это так:

struct B : A
{
   B() = default;

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

( живое демо)

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

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

Другие вопросы по тегам