Можно ли унаследовать конструкторы копирования / перемещения с помощью объявления-использования в с ++17?
struct B {
B(int) {}
B(B const&) {}
};
struct D: B {
using B::B;
};
int main(void) {
B b(5);
D d(b); // error
return 0;
}
C++14 явно исключает конструкторы копирования / перемещения из унаследованных конструкторов в 12.9 [class.inhctor]/p3.
Для каждого конструктора, не являющегося шаблоном, в наборе кандидатов унаследованных конструкторов, кроме конструктора, не имеющего параметров, или конструктора копирования / перемещения, имеющего единственный параметр, конструктор неявно объявляется с теми же характеристиками конструктора, если только не существует объявленный пользователем конструктор с та же подпись в полном классе, где появляется объявление using, или конструктор будет конструктором по умолчанию, копировать или перемещать для этого класса.
Но я не смог найти подробных описаний в C++17. clang/gcc показывают, что конструкторы копирования / перемещения базового класса не наследуются. Может ли кто-нибудь указать, где это объясняется в стандарте? Спасибо.
2 ответа
Новая формулировка находится в [over.match.funcs] / 8:
Конструктор, унаследованный от типа класса
C
([class.inhctor.init]) с первым параметром типа "ссылка на cv1P
”(Включая такой конструктор, созданный из шаблона) исключается из набора функций-кандидатов при создании объекта типа cv2.D
если список аргументов имеет ровно один аргумент иC
ссылка связана сP
а такжеP
ссылка связана сD
. [ Пример:struct A { A(); // #1 A(A &&); // #2 template<typename T> A(T &&); // #3 }; struct B : A { using A::A; B(const B &); // #4 B(B &&) = default; // #5, implicitly deleted struct X { X(X &&) = delete; } x; }; extern B b1; B b2 = static_cast<B&&>(b1); // calls #4: #1 is not viable, #2, #3, and #5 are not candidates struct C { operator B&&(); }; B b3 = C(); // calls #4
- конец примера ]
В вашем примере B
унаследованный конструктор копии исключается из набора кандидатов (этот конструктор имеет первый параметр ссылки типа на const B
, список аргументов имеет ровно один аргумент - b
, а также B
а также D
связаны со ссылками).
Цитируемый вами отрывок на самом деле не предотвращает наследование конструкторов копирования в C++14. Вместо этого подумайте об этом:
B(B const&, int = 42) {}
Это конструктор копирования, но он имеет два параметра. Отрывок исключает только конструктор копирования с одним параметром. И когда вы предоставляете оба аргумента, вы фактически можете инициализироватьD
объект с этим конструктором.
g++
сообщения об ошибках дают некоторое представление.
note: an inherited constructor is not a candidate for initialization from an expression of the same or derived type
Ага! Быстрый поиск в проекте стандарта обнаруживает это
Конструктор, унаследованный от типа класса C (http://eel.is/c++draft/class.inhctor.init), который имеет первый параметр типа "ссылка на cv1 P" (включая такой конструктор, созданный из шаблона), исключается из набора функций-кандидатов при создании объекта введите cv2 D, если список аргументов имеет ровно один аргумент и C связан со ссылкой с P, а P связан со ссылкой с D.