Можно ли унаследовать конструкторы копирования / перемещения с помощью объявления-использования в с ++ 17? - PullRequest
2 голосов
/ 05 мая 2020
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 / g cc показывают, что конструкторы копирования / перемещения базового класса не наследуются. Может ли кто-нибудь указать, где это объясняется в стандарте? Спасибо.

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

Новая формулировка находится в [over.match.funcs] / 8 :

Конструктор, унаследованный от типа C ([class.inhctor.init] ), у которого есть первый параметр типа «ссылка на cv1 P» (включая такой конструктор, созданный из шаблона), исключается из набора функций-кандидатов при создании объекта типа 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 связаны со ссылкой).

1 голос
/ 05 мая 2020

Процитированный вами отрывок на самом деле не предотвращает наследование конструкторов копирования в 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

Ага! Быстрый поиск в черновом стандарте находит this

Конструктор, унаследованный от типа класса C ( class.inhctor.init ), который имеет первый параметр типа «ссылка на cv1 P » (включая такой конструктор, созданный из шаблона) исключается из набора функций-кандидатов при построении объекта типа cv2 D , если аргумент list имеет ровно один аргумент, и C связано со ссылкой на P , а P связано со ссылкой на D.

...