Почему нет признака типа std:: is struct?


Я видел, что для того, чтобы проверить, если тип T это класс, который я могу использовать:

bool isClass = std::is_class<T>::value;

возвращает true для обоих классов и структур. Я знаю, что в C++ они почти одно и то же, но я хотел бы знать, почему нет различия между ними в черте типа. Всегда ли бесполезно проверять эту разницу, или есть еще какая-то причина, которую я не понимаю?

5 54

5 ответов:

возвращает true для обоих классов и структур. Я знаю, что в C++ они почти одно и то же, но я хотел бы знать, почему нет различия между ними в черте типа.

к сожалению это распространенное заблуждение в C++. Иногда это происходит из-за фундаментального непонимания, но в других случаях это происходит из-за двусмысленности в английском языке. Это может исходить из неточной диагностики компилятора, плохо написанных книг, неправильных так ответы...

Вы, наверное, читали что-то вроде этого:

" в C++ нет разницы между структурой и классом, за исключением видимости по умолчанию членов и баз."

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

в самом деле, в C++ не имеет структуры, начиная с 1985 года. Оно есть только классы.

тип типов, которые вы объявляете с ключевым словом class и ключевое слово struct are классы. Период. Ключевое слово struct, и правила видимости, которые являются по умолчанию при определении класса с использованием этого ключевого слова, были сохранены только для обратной совместимости с C ... но это синтаксическая вещь. Это не делает полученные типы На самом деле быть другого рода.

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

невозможно различить разницу в семантике для пустых определений типа

class C {
public:

};

С

struct S {

};

или же

class C {

};

и

struct S {
private:

};

помимо struct vs class ключевое слово, нет никакой поведенческой разницы прощупывается. Смотрите также это Q & A.

Примечание: как заметил @KyleStrand, Деривация также требует явных спецификаторов доступа, поэтому S : private Base {}; и C : Base {}; эквивалентны, то же самое, что S : Base {}; и C : public Base {};, где S - это структура, C - это класс, и Base может быть.

Это одно и то же. Единственное различие (видимость элемента по умолчанию) существует только во время компиляции. В противном случае нет никакой разницы между struct и class.

ETA: что вы, вероятно, хотите-это std::is_pod, который скажет вам, является ли ваш класс "простым старым типом данных". Большая часть обсуждений и комментариев по этому вопросу, по-видимому, указывает на то, что именно этого хотят те, кто считает, что должно быть различие.

Другие правильно указали, что в C++ ключевые слова struct и class имеют то же значение, за исключением разницы в видимости членов.

вызываете ли вы агрегатные типы, определенные таким образом" структуры "или" классы "или" weiruewzewiruz", зависит от вас. В интересах коммуникации, как правило, рекомендуется следовать установленным конвенциям, поэтому я бы посоветовал не "weiruewzewiruz".

также рекомендуется использовать семантические различия в качестве руководство по выбору слов. Использование struct является более распространенным для простых агрегированных данных, которые не имеют много внутренней логики и инвариантов; типичное использование было бы struct point { float x; float y; };. Такие типы часто называют "структурами" или "структурами" в литературе. Было бы не удивительно, если кто-то использует fprintf в C++ первый аргумент называется "указатель на файловую структуру". Файл является примером того, что Скотт Мейерс означает в "более эффективном C++", пункт 34:

это безопасно предположить, что определение структуры, которое компилируется в обоих языки С и C++ -С. а.с] выкладывается таким же образом, как компиляторы.

Что касается языка программирования, то не имеет значения, если определение c++ агрегата данных в вопрос использовал ключевое слово struct или class (со спецификатором общего доступа). struct - Это, пожалуй, более естественным выбором, потому что семантику C++ в совокупности составляют семантику с ключевого слова struct. Кроме того, используя struct позволяет источникам C и c++ легче совместно использовать одно определение типа.

стандарт C++ использует "struct" и "structure" как на естественном, так и на языке программирования, а не только в случаях совместимости: 1.7/5: "структура, объявленная как", или 3.2/4 struct X; // declare X as a struct type. Наиболее интересным является 9/8, закладывающий основу для взаимодействия-критерии:

8 структура стандартной компоновки-это класс стандартной компоновки определиться с классом-ключевые структуры или класса-ключ класс. [...]

как кто-нибудь, читающий это, может утверждать, что в C++ нет структур, вне меня. Это явно не ошибка редактирования, потому что термины "структура" и "класс" явно заданы по отношению друг к другу.


интереснее, чем выбор слов и вопросы вкуса, однако, являются очевидными, проверяемыми различиями. При каких обстоятельствах агрегат C++ сопоставим и совместим с C struct? Возможно, этот вопрос лежал в основе вашего вопроса? Типовая форма стандарта, упомянутая в цитате, является критерием. Он подробно описан в 9/7 и по существу предписывает, что

  • только один класс в иерархии наследования может иметь нестатические определения элементов данных (вероятно, потому, что стандарт не имеет требуется указать порядок элементов данных, определенных на разных уровнях в такой иерархии);
  • виртуальные функции или виртуальные базовые классы не допускаются (из-за дополнительных данных экземпляра, необходимых для информации о времени выполнения);
  • все члены имеют одинаковый "контроль доступа" (либо публичный, защищенный или частный; вероятно, потому, что реализация может свободно заказывать контроль доступа).

стандарт тогда говорит

9 [ Примечание: классы стандартной компоновки полезны для общения с кодом, написанным на других языках программирования. Их расположение указано в 9.2.-конец Примечание ]

конечно, определение структуры, которое компилируется в C, удовлетворяет этим критериям, следовательно, утверждение Скотта Мейерса. FILE от stdio.h-яркий, не совсем тривиальный пример. Обратите внимание, что стандарт не дает гарантий, поскольку макет объекта зависит от реализации и может изменяться только с помощью параметр компилятора.

имеет ли класс стандартную компоновку, можно проверить с помощью признака типа std::is_standard_layout<T>. Следующая программа, которая вдохновлена пример на cppreference, проверяет основные случаи, изложенные в стандарте.

#include <cstdio>
#include <typeinfo>
#include <type_traits>

using namespace std;

struct funcOnlyT // fine
{
    int f();
};

class podT {   // "class" is ok
    int m1;
    int m2;
};

struct badAccessCtrlT { // bad: public/private
    int m1;
private:
    int m2;
};

struct polymorphicT {  // bad: polymorphic
    int m1;
    int m2;
    virtual void foo();
};


struct inheritOkT: podT // ok: inheritance, data only on one level
{
    int f();
};


struct inheritPlusDataT: podT // bad: inheritance, data on 2 levels
{
    int m3;
};

template<typename T1, typename T2>
struct templT     // ok with std layout types T1, T2
{
    T1 m1;
    T2 m2;
};

// print type "name" and whether it's std layout
template<typename T>
void printIsStdLayout()
{
    printf("%-20s: %s\n", 
            typeid(T).name(),
            std::is_standard_layout<T>::value 
                ? "is std layout" 
                : "is NOT std layout");
}

int main()
{
    printIsStdLayout<funcOnlyT>();
    printIsStdLayout<podT>();
    printIsStdLayout<badAccessCtrlT>();
    printIsStdLayout<polymorphicT>();
    printIsStdLayout<inheritOkT>();
    printIsStdLayout<inheritPlusDataT>();
    printIsStdLayout<templT<int, float> >();
    printIsStdLayout<FILE>();
}

пример:

$ g++ -std=c++11 -Wall -o isstdlayout isstdlayout.cpp && ./isstdlayout
9funcOnlyT          : is std layout
4podT               : is std layout
14badAccessCtrlT    : is NOT std layout
12polymorphicT      : is NOT std layout
10inheritOkT        : is std layout
16inheritPlusDataT  : is NOT std layout
6templTIifE         : is std layout
9__sFILE64          : is std layout
C++11 §9/8 ([класса]/8):

" A структура стандартной компоновки-это класс стандартной компоновки, определенный с помощью class-keystruct или class-keyclass. А объединение стандартных макетов-это класс стандартной компоновки, определенный с помощью class-keyunion.

C++11 §9/10 ([класса]/10):

" A POD struct является несоюзным классом, который является как тривиальным классом, так и классом стандартной компоновки и не имеет нестатические элементы данных типа non-POD struct, non-POD union (или массив таких типов). [...]

С a POD struct является классом стандартной компоновки это подмножество структура стандартной компоновки. насколько я знаю это самое общее значение struct в стандарте C++. И поэтому, по-видимому, то, что вы ищете, - это признак типа или набор признаков типа, который позволяет вам идентифицировать структура стандартной компоновки как таковой.

и вуаля, глядя на список черт типа есть is_class и is_standard_layout. Когда тип satisifies 1both это "структура". Или точнее, это структура стандартной компоновки, как определено C++11 §9/8.


о

" я хотел бы знать, почему нет различия между [class и struct] в типе признака

Ну, нет. Вот это is_standard_layout черта.


о

" всегда ли бесполезно проверять эту разницу, или есть еще какая-то причина, которую я не понимаю?

нет, это не бесполезно проверять эту разницу. Стандарт определяет стандартные-макета по той причине, что это очень практически полезным. Как отмечает сам стандарт,

C++11 §9/9 ([класса]/9):

" [Примечание: классы стандартной компоновки полезны для связи с кодом, написанным на других языках программирования. Их расположение указано в 9.2.- Конечная нота ]


Примечания:
1 The is_class черта истинна для class или struct, а не union, хотя стандарт определяет, что "профсоюз-это класс". Т. е. признак более специфичен, чем общая терминология.