2017-09-13 17 views
35

주어진 형이 무엇이든 파생되면 참이 될 타입 형질이 필요하다. 그렇지 않으면 거짓이된다. 예를 들어C++ 17에서는 구조체/클래스에 기본이 있는지 여부를 감지 할 수 있습니까?

:

template<class T> 
struct is_inherit 
    //... logic of inheritance detection 
    ; 

template<class T> 
void AppLogic(){ 
    if constexpr(is_inherit<T>::value) { 
     puts("T has base"); 
     //... 
    } else { 
     puts("T doesn't have base"); 
     //... 
    } 
} 

struct A {}; 
struct C {}; 
struct B: C {}; 

int main() { 
    AppLogic<A>(); // print: T doesn't have base 
    AppLogic<B>(); // print: T has base 
} 

이 가능 어떻게 든 "is_inherit"특성 구조체를 구현하는 방법?


왜?

Windows x64 용 수동 스택 프레임 빌더를 개발 중입니다. https://docs.microsoft.com/en-us/cpp/build/return-values-cpp 설명서에 따르면 유형이 : 1, 2, 4, 8, 16, 32 또는 64 비트의 길이를 가지면 유형이 :

  • 입니다.
  • 에는 사용자 정의 생성자, 소멸자 또는 복사 할당 연산자가 없습니다.
  • 에는 비공개 또는 비보호 데이터 멤버가 없습니다.
  • 에는 참조 유형의 비 정적 데이터 멤버가 없습니다.
  • 에는 기본 클래스가 없습니다.
  • 에는 가상 기능이 없습니다.
  • 및 이러한 요구 사항을 충족하지 않는 데이터 멤버가 없습니다.

그런 다음 반환 값은 RAX 레지스터에 있습니다. 그렇지 않으면 함수 에 탐지하고 처리해야하는 숨겨진 인수가 있습니다. 정의는 C++ 11 표준에 변경

때문에, 우리는하지 않는 것이 좋습니다 :이 변경

는 C++ 11 그러나, C++ 03 POD의 정의로 사용 이 테스트에는 std::is_pod을 사용하십시오.

지금까지는 유형이 C++ 03 POD의 정의를 충족시키는 지 여부를 감지 할 수있었습니다. 그러나 C++ 17에서는 집계 규칙이 변경되어 내 솔루션이 손상되었습니다.

T가 유형이 기본 클래스인지 여부를 어떻게 든 감지 할 수 있으면 내 솔루션이 다시 작동합니다.

+0

기본 *이 일반적으로 * 인 경우? "속임수"없이는 그렇게 할 수 있다고 생각하지 마십시오. – StoryTeller

+1

C++에 인트로 스펙 션이 추가 될 때까지 기다리거나 컴파일러 관련 트릭을 찾아야합니다. 나는 네가 그렇게 할 수 있다고 생각하지 않는다. 그러나 비토리오 로미오 (Vittorio Romeo)가 말했듯이 이것은 XY 문제 일 수 있습니다. 왜 이것을 필요로합니까? 원래의 문제를 해결할 수있는 더 좋은 방법이있을 수 있습니다. – bolov

+0

그래, 일반적으로, 주어진 유형이 어떤 기지를 가지고 있는지 감지합니다. std :: is_base_of와 같은 것이 없습니다. 2 가지 유형을 부여해야하며 특성 반환 값은 X가 Y를 상속받습니다. – Nyufu

답변

31

예, 적어도 집계가 가능합니다.

먼저 그 템플릿 파라미터 중 적합한 염기로 변환하는 클래스 템플릿을 구성 :

: 그러면 템플릿 파라미터 T 집계 작도 유형 any_base<T> 값으로부터 유무를 검출

template<class T> 
struct any_base { 
    operator T() = delete; 
    template<class U, class = std::enable_if_t<std::is_base_of_v<U, T>>> operator U(); 
}; 

template<class, class = void> struct has_any_base : std::false_type {}; 
template<class T> 
struct has_any_base<T, std::void_t<decltype(T{any_base<T>{}})>> : std::true_type {}; 

Example.

+4

을 읽으십시오 if 나는 class E {E (B &) {}}와 같은 클래스를 가졌다; 나는 has_any_base_v가 참일 것이라고 두려워한다. – gu1d0

+1

@ gu1d0 오, 그래, std :: is_base_of는 클래스가 그것의 자신의베이스라고 말한 것을 잊었다. 덕분에 – ecatmur

+0

@ gu1d0 그래,하지만 E가 생성자를 가지고 있다면 사소한 것이 아니므로 집계가 아니다 ecatmur는 "적어도 집계를 위해"작동한다. 이것은 내 C의 일부가 될 것이다. ++ 03 POD 검출 특성 때문에이 솔루션으로 충분하다. ' 구조체 is_cpp03_pod : std :: bool_constant &&! has_any_base_v > {};' – Nyufu

8

"T이 무엇으로부터 도출되는지"확인하는 것은 적어도 표준을 따르지 않는 방식으로는 가능하지 않습니다.

+0

std :: is_base_of –

+1

@ Dúthomhas : 질문 –