Я исследовал уродливый мир std::intializer_list
.
Насколько я понял из стандарта:
§ 11.6.4 :
Объект типа std :: initializer_list создается из списка инициализаторов, как если бы реализация генерировала и материализовала (7.4) значение типа «массив из N const E», где N - количество элементов в списке инициализатора., Каждый элемент этого массива инициализируется копией с соответствующим элементом списка инициализаторов , и объект std :: initializer_list создается для ссылки на этот массив.[Примечание: конструктор или функция преобразования, выбранная для копии , должны быть доступны (пункт 14) в контексте списка инициализатора.- конец примечания] [...]
Итак, если тип E
является классом , я ожидаю конструктор копирования чтобы быть вызванным.
Следующий класс не позволяет создавать копии:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
};
Я собираюсь создать экземпляр std::initializer_list
с этим классом.
#include <vector>
void foo() {
std::vector<NonCopyable>{NonCopyable{}, NonCopyable{}};
}
С g++-8.2 -std=c++14
я получаю то, что ожидаю, ошибка компилятора:
error: use of deleted function 'NonCopyable::NonCopyable(const NonCopyable&)'
.
Отлично!
Однако поведениеизменения с новым стандартом.
Действительно, g++-8.2 -std=c++17
компилируется.
Тест проводника компилятора
Я думал, что это из-засначала новое требование о copy elision
, предоставляемое новым стандартом.
Однако, при изменении реализации стандартной библиотеки (c ++ 17) возникает ошибканазад:
clang-7 -std=c++17 -stdlib=libc++
не удалось:
'NonCopyable' has been explicitly marked deleted here NonCopyable(const NonCopyable&) = delete;
Тест проводника компилятора
Так что же яотсутствует?
1) Требуется ли C ++ 17 copy-elision в копии конструкции элементов initializer_list
?
2) Почему реализация libc++
здесь не компилируется?
Отредактируйте Обратите внимание, что в примере g++ -std=c++17
(который компилируется), если я изменяю конструктор по умолчанию на "определенный пользователем":
struct NonCopyable {
NonCopyable();
NonCopyable(const NonCopyable&) = delete;
};
программа небольше не компилируется (не из-за ошибки ссылки).
Пример компилятора