Почему тип CopyConstructible также должен быть MoveConstructible? - PullRequest
0 голосов
/ 06 февраля 2019

Как указано в cppreference , требование для типа T должно быть CopyConstructible , чтобы оно также было MoveConstructible .

Черновик для концепции STL CopyConstructible содержит:

template <class T>
concept CopyConstructible =
   std::MoveConstructible<T> &&
   std::Constructible<T, T&> && std::ConvertibleTo<T&, T> &&
   std::Constructible<T, const T&> && std::ConvertibleTo<const T&, T> &&
   std::Constructible<T, const T> && std::ConvertibleTo<const T, T>;

, которая поддерживает именованный оператор требования.Учитывая приведенное выше определение, тип типа:

struct HaveCopy {
   HaveCopy(const HaveCopy&)  = default;
   HaveCopy(HaveCopy&&)       = delete;
   HaveCopy& operator= (const HaveCopy&)  = default;
   HaveCopy& operator= (HaveCopy&&)       = delete;
};

не проходит простой тест:

static_assert(std::CopyConstructible<HaveCopy>);

, в то время как он проходит старый:

static_assert(std::is_copy_constructible<HaveCopy>::value);

Итак,вопрос почему ?Каково намерение комитета по стандартам в этом вопросе?HaveCopy не является перемещаемым конструктором, но, по моему мнению, в значительной степени конструктивен для копирования, и std::is_copy_constructible<> согласен со мной.

То же поведение также наследуется концепцией Copyable , а именно:

template <class T>
concept Copyable =
   std::CopyConstructible<T> &&
   std::Movable<T> &&
   std::Assignable<T&, const T&>;

Итак, тест:

static_assert(std::Copyable<HaveCopy>);

также не пройдёт.На этот раз отказ удваивается.И CopyConstrucible<>, и Movable<> не согласны с тем, что HaveCopy можно копировать.

Обсуждение здесь чем-то похоже, но не отвечает на , почему .Зачем нам это поведение?Исключает ли этот вид проверки допустимые типы копируемых конструктивов или HaveCopy вообще не копируется конструктивно?Последнее кажется мне действительно странным, если это правда.

Есть мысли?

1 Ответ

0 голосов
/ 06 февраля 2019

Да, CopyConstructible концепция совершенно отличается от черты типа std::is_copy_constructible.Вы сосредотачиваетесь на конструкторе перемещения, но есть и много других случаев, которые следует рассмотреть.Как вы думаете, этот тип должен быть CopyConstructible?

struct A {
    A(A&) = delete;
    A(A const&);
};

Как насчет этого?

struct B {
    explicit B(B const&);
};

Дело в том, что существует бесконечное множество комбинаций конструкторов, которые вы можете написать.Это не значит, что они все значимы или заслуживают поддержки.Наличие типа с конструктором копирования, но с удаленным конструктором перемещения просто не имеет смысла.

Concepts - это не просто синтаксическая проверка, а также соблюдение семантических требований, требующих значимых типов, которые в итоге становятся проще в кодировании.Если вы просто проверяете is_copy_constructible, все, что вы позволяете себе делать, это явно конструировать ваш тип из const lvalue.Запись T x = y;, даже если y является const T, уже выходит за рамки этого!Это может буквально означать, что означает конструирование копии, но это гораздо менее значимо, чем более широкое «Я могу построить T из T» - что намного ближе к тому, о чем мы действительно думаем, когда рассматриваем копирование.Это то, что дает нам понятие CopyConstructible.

Когда вы просматриваете библиотеку, существуют другие концепции, которые требуют большего (синтаксически и семантически), чем может предложить прямой перевод их имени.EqualityComparableWith<T,U> проверяет не только то, что я могу написать t == u, но также u == t, t != u и u != t.StrictTotallyOrdered не только проверяет операторы заказа, но и также проверяет ==.Наличие связного целого важно.

...