Какие структуры данных STL с сохраненным неполным типом могут использоваться в качестве члена класса? - PullRequest
1 голос
/ 01 февраля 2020

Насколько я знаю, начиная с C ++ 17 некоторые структуры данных STL могут «существовать» с неполным типом в качестве параметра шаблона, который описывает тип хранимого. Например, я могу использовать std::unique_ptr<Incomplete> (хотя я не уверен, что это структура данных) или std::vector<Incomplete> в качестве членов класса, если все свойства класса (для которых необходимо определение Incomplete) реализованы в отдельном . cpp file:

class Incomplete;
using Complete = int;
class Foo {
private:
  std::unique_ptr<Incomplete> u_p;
  std::vector<Incomplete> v;
  std::deque<Incomplete> d;
  std::list<Incomplete> l;
  std::set<Incomplete> s;
  std::unordered_map<Complete, Complete> u_m_cc;
  std::unordered_map<Complete, Incomplete> u_m_ci;
  std::unordered_map<Incomplete, Complete> u_m_ic;
  std::unordered_map<Incomplete, Incomplete> u_m_ii;
public:
  // implemented in a separate .cpp which has Incomplete defined:
  Foo();
  Foo(Foo&&);
  Foo& operator=(Foo&&);
  Foo(Foo const&);
  Foo& operator=(Foo const&);
  ~Foo();
};

Итак, какие из перечисленных выше элементов данных действительны для такого использования? А как насчет других структур данных, умных указателей и т. Д. c.?

Ответы [ 2 ]

2 голосов
/ 01 февраля 2020

Предполагая, что ни один из членов класса не используется явно или неявно, пока тип не будет завершен:

Аргумент шаблона всегда может быть неполным для std::unique_ptr и std::shared_ptr начиная с C ++ 11, см. [unique.ptr] / 5 и [util.smartptr.shared] / 2 соответственно.

Поддержка неполных типов в контейнерах была добавлена ​​с помощью N4510 до C ++ 17, но только для

std::vector
std::list
std::forward_list

и только в том случае, если используемый распределитель удовлетворяет требованиям полноты распределителя , а именно, что даже если сам тип значения не является полным, тип распределителя X сам по себе является полным типом, как и все члены std::allocator_traits<X>, кроме ::value_type. Распределитель по умолчанию std::allocator удовлетворяет этим требованиям.

Ни один из других контейнеров не может использоваться с неполными типами. Согласно предложению, связанному выше, область действия была ограничена этими тремя контейнерами " в качестве первого шага ", потому что основные реализации уже поддерживали его.

1 голос
/ 01 февраля 2020

, поскольку в C ++ 17 некоторые структуры данных STL могут «существовать» с неполным типом в качестве параметра шаблона, описывающего сохраненный тип.

Это неверно.

Начиная с C ++ 17, некоторые типы STL могут быть объявлены с неполным типом в качестве параметра шаблона.

К тому времени, когда типы созданы , типы должны быть полными.

Например: (непроверенный код)

struct T; // incomplete
using TV = std::vector<T>; // declared a type using incomplete type T; fine.

TV tv0; // attempt to declare a variable of type TV; fails to compile.

struct T { int v; }; // T is now complete
TV tv1; // compiles
...