g++ --version
дает:
g++.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 4.9.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Программа:
#include <memory>
#include <type_traits>
#include <unordered_map>
static_assert(!std::is_copy_constructible<std::unordered_map<int,std::unique_ptr<int>>>::value,"Copyable");
int main () { }
Результат компиляции:
.\unorderedmapcopyable.cpp:5:1: error: static assertion failed: Copyable
static_assert(!std::is_copy_constructible<std::unordered_map<int,std::unique_ptr<int>>>::value,"Copyable");
^
Соответствующий стандарт:
В контейнерах, которые можно копировать
Для утверждений X u(a)
и X u=a
для допустимого значения для некоторого типа контейнера X
, который содержит тип T
, где a
- значение типа X
:
Требуется:
T
естьCopyInsertable
вX
§23.2.1 [container.requirements.general]
Мое понимание этого: Если T
(в нашем случае std::pair<const int,std::unique_ptr<int>>
) не CopyInsertable
в X
(в нашем случае std::unordered_map<int,std::unique_ptr<int>>
), то X u(a)
и X u=a
не были хорошо сформированы.
Вкл CopyInsertable
T
CopyInsertable
вX
означает, что в дополнение кT
, являющемусяMoveInsertable
, вX
, следующее выражение хорошо сформировано:
allocator_traits<A>::construct(m, p, v)
и его оценка приводит к следующему постусловию: Значение
v
не изменяется и эквивалентно*p
.
Мое понимание этого: std::pair<const int,std::unique_ptr<int>>
не CopyInsertable
, из-за того, что std::unique_ptr<int>
не копируется:
Каждый объект типа
U
, созданный из шаблонаunique_ptr
, указанного в этом подпункте [...], не являетсяCopyConstructible
иCopyAssignable
.§20.8.1 [unique.ptr]
И из-за того, что конструктор копирования std::pair<const int,std::unique_ptr<int>>
по умолчанию:
pair(const pair&) = default;
§20.3.2 [pairs.pair]
И из-за того, что std::pair<const int,std::unique_ptr<int>>
имеет член типа std::unique_ptr<int>
:
template <class T1, class T2> struct pair {
[...]
T2 second;
§20.3.2 [pairs.pair]
И из-за того, что дефолтные конструкторы копий удаляются, когда это не так, что все члены типа CopyConstructible
:
По умолчанию конструктор copy/move для класса
X
определяется как удаленный, если X имеет:[...]
- нестатический член данных типа класса
M
(или его массив), который нельзя скопировать/перемещать, поскольку разрешение перегрузки, применяемое к соответствующему конструкторуM
, приводит к [...] функции, которая удаляется [...]§12.8 [class.copy]
Вкл std::is_copy_constructible
Для ссылочного типа
T
, тот же результат, что иis_constructible<T,const T&>::value
, иначеfalse
.§20.10.4.3 [meta.unary.prop]
Мое понимание/чтение этого: std::is_copy_constructible<std::unordered_map<int,std::unique_ptr<int>>
совпадает с std::is_constructible<std::unordered_map<int,std::unique_ptr<int>,std::unordered_map<int,std::unique_ptr<int> &>
.
Вкл. std::is_constructible
Учитывая следующий прототип функции:
template <class T> add_rvalue_reference_t<T> create() noexcept;
условие предиката для специализированной специализации
is_constructible<T, Args...>
должно выполняться тогда и только тогда, когда следующее определение переменной будет хорошо сформировано для некоторой изобретенной переменнойT
:
T t(create<Args>()...);
§20.10.4.3 [meta.unary.prop]
Мое понимание этого: std::is_constructible<std::unordered_map<int,std::unique_ptr<int>>,std::unordered_map<int,std::unique_ptr<int> &>
должно быть std::false_type
, а не std::true_type
, так как X u(a)
не является корректным.
Мой вопрос
Должен ли быть принят этот код? Является ли это ошибкой GCC/libstdС++, или есть что-то в стандарте, который мне не хватает?
В настоящее время у меня нет доступа к Clang или MSVС++, иначе я бы тестировал их.