Почему класс со ссылками не придерживается standard_layout?
Выполнение следующего кода:
#include <iostream>
#include <type_traits>
struct s_ref {
int &foo;
};
struct s_ptr {
int *foo;
};
int main(int argc, char *argv[])
{
std::cout << "s_ref is_standard_layout:" << std::is_standard_layout<struct s_ref>::value << std::endl;
std::cout << "s_ptr is_standard_layout:" << std::is_standard_layout<struct s_ptr>::value << std::endl;
return 0;
}
приводит к:
s_ref is_standard_layout:0
s_ptr is_standard_layout:1
Основываясь на использовании стандартной компоновки (то есть: "Стандартные типы макетов полезны для общения с кодом, написанным на других языках программирования" ), это имеет смысл, но я не уверен, что является нарушением правила:
Класс стандартного макета - это класс (определенный с помощью класса, структуры или союз), что:
-
не имеет виртуальных функций и виртуальных базовых классов.
-
имеет тот же контроль доступа (закрытый, защищенный, общедоступный) для всех его нестатических членов данных.
-
либо не имеет нестатических членов данных в самом производном классе и не более одного базового класса с нестатическими элементами данных, либо не имеет базовые классы с нестатическими членами данных.
-
его базовый класс (если он есть) сам по себе также является классом стандартного макета.
-
И не имеет базовых классов того же типа, что и его первые нестатические данные член.
Изменить: цитата из: http://www.cplusplus.com/reference/type_traits/is_standard_layout/, но http://en.cppreference.com/w/cpp/concept/StandardLayoutType также похожа.
Ответы
Ответ 1
Точка стандартной концепции стандартного класса компоновки С++ заключается в том, что экземпляр такого класса может быть надежно доступен или скопирован в байты, который, как отмечает стандарт С++ 11 в его § 9/9, делает такой класс
", полезный для общения с кодом, написанным на других языках программирования
Однако стандарт С++ не требует ссылки на использование хранилища вообще. Это не предмет. Вы не можете принять его адрес. Поэтому он не может быть (надежно) скопирован в байты или доступен как байты. И поэтому он несовместим с понятием стандартных классов макета.
В формальном,
С++ 11 §9/7:
" Класс стандартного макета - это класс, который:
- не имеет нестатических элементов данных типа нестандартного макета (или массива таких типов) или ссылки,
Ответ 2
Я не знаю, откуда вы получили эту цитату, но она не принимает соответствующее правило из стандарта.
(N3337) [class]/7:
Класс стандартного макета - это класс, который:
- не имеет нестатических элементов данных типа нестандартного макета (или массива таких типов) или ссылки,
- не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
- имеет тот же контроль доступа (раздел 11) для всех нестатических членов данных,
- не имеет базовых классов нестандартной компоновки,
- либо не имеет нестатических элементов данных в самом производном классе и не более одного базового класса с нестатические члены данных или не имеет базовых классов с нестатическими элементами данных и
- не имеет базовых классов того же типа, что и первый нестатический элемент данных .108
Ответ 3
В n4140 вы можете прочитать:
9 Классы (7.1)
Класс стандартного макета - это класс, который:
- не содержит нестатических элементов данных класса нестандартного макета (или массива таких типов) или ссылки,
[править]
для получения дополнительной информации о том, почему класс со ссылками не является стандартным макетом, прочитайте этот отличный ответ: Стандартная компоновка и ссылки на С++