Наследование конструктора и предоставление новой перегрузки: базовый конструктор без аргументов, по-видимому, не участвует в разрешении перегрузки
Тесты показывают странное поведение (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) предполагает, что легкость и симметрия этого исправления более или менее являются движущим фактором, влияющим на решение, хотя я все же нахожу это несколько неудовлетворительным. Ну что ж.
Конструкторы копирования и по умолчанию не пересылаются, что относится к существующим правилам для неявного объявления конструкторов копирования / по умолчанию.