std :: is_struct 유형 특성이없는 이유는 무엇입니까?
유형 T
이 클래스 인지 확인하기 위해 사용할 수있는 것을 보았습니다 .
bool isClass = std::is_class<T>::value;
클래스와 구조체 모두에 대해 true를 반환합니다. 나는 C ++에서 그것들이 거의 똑같다는 것을 알고 있지만, 유형 특성에서 그들 사이에 차이가없는 이유를 알고 싶습니다. 이 차이를 확인하는 것이 항상 쓸모가 있습니까? 아니면 이해하지 못하는 이유가 더 있습니까?
클래스와 구조체 모두에 대해 true를 반환합니다. 나는 C ++에서 그것들이 거의 똑같다는 것을 알고 있지만, 유형 특성에서 그들 사이에 차이가없는 이유를 알고 싶습니다.
불행히도 이것은 C ++에서 일반적인 오해입니다. 때로는 근본적인 오해에서 비롯되지만 때로는 영어의 모호함에서 비롯됩니다. 부정확 한 컴파일러 진단, 잘못 쓰여진 책, 잘못된 SO 답변에서 비롯 될 수 있습니다.
아마도 다음과 같이 읽었을 것입니다.
"멤버와베이스의 기본 가시성을 제외하고는 구조체와 클래스간에 C ++에 차이가 없습니다."
이 구절은 오해의 소지가있는 의미로 해석 될 수 있습니다 . "차이 없음"과 같은 구절을 사용할 때 정체성 과 평등 의 개념 을 구별하기 어렵 기 때문 입니다.
사실 C ++에는 1985 년 이후로 구조체가 없었습니다. 클래스 만 있습니다.
키워드 class
와 키워드로 선언하는 유형 struct
은 클래스 입니다. 기간. 키워드 struct
및 해당 키워드를 사용하여 클래스를 정의 할 때 기본값 인 가시성 규칙은 C…와의 하위 호환성을 위해서만 유지되었지만 구문 문제입니다. 결과 유형이 실제로 다른 종류가되는 것은 아닙니다.
유형 특성은 문자 그대로 만들 것이 없기 때문에 구별하지 않습니다.
다음과 같은 빈 정의에 대한 의미 체계의 차이를 구별하는 것은 불가능합니다.
class C {
public:
};
...에서
struct S {
};
또는 유사하게
class C {
};
과
struct S {
private:
};
struct
vs class
키워드를 제외하고는 감지 할 수있는 행동 차이가 없습니다. 이 Q & A를 참조하십시오 .
참고 : @KyleStrand에서 언급했듯이 파생에는 명시 적 액세스 지정자도 필요하므로 S : private Base {};
and C : Base {};
는 동일합니다. S : Base {};
and 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 ++에서 사용하는 누군가 가 첫 번째 인수를 "FILE 구조체에 대한 포인터"라고 언급하는 것은 놀라운 일이 아닙니다 . FILE은 "More Effective C ++", Item 34에서 Scott Meyers가 의미하는 바의 예입니다.
두 언어 [C 및 C ++ -pas]로 컴파일되는 구조 정의가 두 컴파일러에 의해 동일한 방식으로 배치된다고 가정하는 것이 안전합니다.
자연어와 관련하여 "구조"라는 단어 선택은 우연이 아닙니다. Meyers는 비트 수준까지 두 언어에서 동일한 의미를 갖는 평범한 오래된 데이터 집합체에 대해 이야기하고 있습니다.
프로그래밍 언어와 관련하여 문제가되는 데이터 집합의 C ++ 정의가 키워드 struct
또는 class
(공용 액세스 지정자 사용)을 사용하는지 여부는 중요하지 않습니다 . struct
집계의 C ++ 의미 체계가 C 구조체의 의미 체계이기 때문에 아마도 더 자연스러운 선택 일 것입니다. 또한를 사용 struct
하면 C 및 C ++ 소스 모두 하나의 유형 정의를 더 쉽게 공유 할 수 있습니다.
C ++ 표준은 상호 운용성의 경우뿐만 아니라 자연어와 프로그래밍 언어 모두에서 "struct"및 "structure"를 사용합니다. 1.7 / 5 : "A structure declaration as"또는 3.2 / 4 struct X; // declare X as a struct type
. 가장 흥미로운 것은 9/8로 interop-criteria의 기반을 마련하는 것입니다.
8 표준 레이아웃 구조체는 클래스 키 구조체 또는 클래스 키 클래스로 정의 된 표준 레이아웃 클래스입니다. [...]
이것을 읽는 사람이 C ++에 구조체가 없다고 주장 할 수있는 방법은 저를 넘어선 것입니다. "구조체"와 "클래스"라는 용어가 서로 관련하여 명시 적으로 설정되어 있기 때문에 이것은 분명히 편집 오류가 아닙니다.
그러나 단어 선택과 맛의 문제보다 더 흥미로운 것은 명백하고 검증 가능한 차이입니다. C ++ 집계는 어떤 상황에서 C와 호환되고 호환 struct
됩니까? 아마도이 질문이 귀하의 질문의 기초가 되었습니까? 견적서에 언급 된 표준 레이아웃이 기준입니다. 9/7에 자세히 설명되어 있으며 기본적으로
- 상속 계층 구조의 한 클래스에만 비 정적 데이터 멤버 정의가있을 수 있습니다 (아마도 표준이 계층 구조의 다른 수준에서 정의 된 데이터 요소의 순서를 지정하지 않기 때문일 수 있습니다).
- 가상 기능 또는 가상 기본 클래스는 허용되지 않습니다 (런타임 정보에 필요한 추가 인스턴스 데이터로 인해).
- 모든 구성원은 동일한 "액세스 제어"(공개, 보호 또는 개인, 아마도 액세스 제어에 의해 구현을 주문할 수 있기 때문에)를 갖습니다.
표준은 다음과 같이 말합니다.
9 [참고 : 표준 레이아웃 클래스는 다른 프로그래밍 언어로 작성된 코드와 통신하는 데 유용합니다. 레이아웃은 9.2에 지정되어 있습니다 .—end note]
물론 C로 컴파일되는 구조체 정의는 이러한 기준을 충족하므로 Scott Meyers의 주장입니다. FILE
from stdio.h는 눈에 띄는, 아주 사소한 예입니다. 객체 레이아웃은 구현에 따라 다르며 컴파일러 옵션으로 만 변경 될 수 있기 때문에 표준은 보장하지 않습니다.
클래스에 표준 레이아웃이 있는지 여부는 유형 trait으로 테스트 할 수 있습니다 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) :
C ++ 11 §9 / 10 ([클래스] / 10) :" 표준 레이아웃 구조체 으로 정의 된 표준 레이아웃 클래스 클래스 키
struct
또는 클래스 키class
. 표준 레이아웃 조합은 으로 정의 된 표준 레이아웃 클래스 클래스 키union
.
” A POD struct is a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). […]
Since a POD struct is a standard-layout class it is a subset of standard-layout struct. As far as I know this is the most general meaning of struct in the C++ standard. And so presumably what you're looking for is a type trait or set of type traits that lets you identify a standard-layout struct as such.
And voilà, looking at the list of type traits there's is_class
and is_standard_layout
. When a type satisifies ¹both it's a “struct”. Or more precisely, it's a standard-layout struct, as defined by C++11 §9/8.
Regarding
” I'd like to know why there's not a distinction between [class and struct] in the type trait
Well, there is. That's the is_standard_layout
trait.
Regarding
” Is it always useless to check this difference, or is there some more reason that I don't understand?
No, it's not useless to check this difference. The standard defines standard-layout for the reason that it's very practically useful. As the standard itself notes,
C++11 §9/9 ([class]/9):” [Note: Standard-layout classes are useful for communicating with code written in other programming languages. Their layout is specified in 9.2.—end note ]
Notes:
¹ The is_class
trait is true for a class
or struct
, but not for a union
, even though the standard defines that “a union is a class”. I.e. the trait is more specific than the general terminology.
ReferenceURL : https://stackoverflow.com/questions/32719880/why-is-there-not-an-stdis-struct-type-trait
'developer tip' 카테고리의 다른 글
Twitter Bootstrap은 li에 활성 클래스를 추가합니다. (0) | 2020.12.26 |
---|---|
Java 개발자를위한 최고의 무료 Eclipse 플러그인은 무엇입니까? (0) | 2020.12.26 |
Mac 프롬프트 "권한이 거부되었습니다"에서 스크립트 실행 (0) | 2020.12.26 |
함수, 바인딩되지 않은 메서드 및 바인딩 된 메서드의 차이점은 무엇입니까? (0) | 2020.12.25 |
Flask에서 url_for ()가 사용할 도메인을 어디에서 정의합니까? (0) | 2020.12.25 |