2017-10-30 17 views
1

하나의 인수로 선언을 사용하는 매크로를 작성하고 있습니다. 은 매크로을 매크로 내에서 유형식별자 인수로 분리하지 않고 매크로에서 추론 할 수 있습니까?선언 유형을 유추

#define M(declaration) \ 
    declaration;  \ 
    static_assert(sizeof(/* deduce type of 'declaration' */) == 4, "!") 

M(int i); 
M(double d{3.14}); 
M(std::string s{"Hello, world!"}); 

다음 구현 일하는 것이하지만 덜 사용자 친화적 (IMO) 느낌 :

#define M(type, identifier) \ 
    type identifier;  \ 
    static_assert(sizeof(type) == 4, "!") 

M(int, i); 
M(double, d{3.14}); 
M(std::string, s{"Hello, world!"}); 

가능하다면, 나는 하나의 인수로 선언을하는 것을 선호합니다.


관련 질문 :Macro to get the type of an expression; 하지만 내 예제 (컴파일러 오류 : 예상 중첩 된 이름 지정자)에서 작동하도록 해당 코드를 가져 오지 못했습니다.

+0

마지막에 식별자를 인쇄하려면 정적 어설트를 사용 하시겠습니까? 왜냐하면 그렇지 않다면 전 처리기를 버리는 해결책이 있기 때문입니다. – StoryTeller

+0

@StoryTeller 제가 식별자를 반드시 필요로하지는 않습니다. 그러나 여러 가지 솔루션에 대해 생각해 볼 수 있다면 모든 것에 관심이있을 것입니다. –

답변

2

정적 어설 션 메시지가 실제로 매우 단순한 경우 "!" 전처리 프로그램을 도울 것을 제안합니다. 대신 당신을 위해 형식 시스템 작동을 확인하십시오

namespace detail { 
    template<typename T> 
    struct check_declared_type { 
    using type = T; 
    static_assert(sizeof(type) == 4, "!"); 
    }; 
} 

template<typename T> 
using M = typename detail::check_declared_type<T>::type; 

// .. Later 

int main() { 
    M<int> i; 
    M<double> d{3.14}; 
    M<std::string> s{"Hello, world!"}; 
} 

1을 - 특히, 당신이 당신을 위해 무엇을 캐릭터 라인 화하는 전처리가 필요하지 않은 경우.

+0

내 문제를 해결하고 매크로를 피할 수있게 해줍니다. 감사합니다! 'static_assert'에서 식별자를 사용하고 싶다면 해결책이 있습니까? –

+0

@MaartenBamelis - 그러면 프리 프로세서를 다시 불러들이는 것이 필요합니다. 그리고 다시 1 제곱으로 돌아갑니다. – StoryTeller

+0

그렇다면 C++에서 선언 유형을 추론 할 수 없다고 결론 내릴 수 있습니까? 'decltype'과 다른 컴파일 타임 트릭의 영리한 조합조차도? –

1

이 매크로는 모든 예제 작동한다고하지만 불쾌한 문제가 않습니다

#define M(declaration) \ 
    declaration;  \ 
    do { \ 
     struct dummy__ { declaration; }; \ 
     static_assert(sizeof(dummy__) == 4, "!"); \ 
    } while (false) 

문제는 클래스 정의 내에서 초기화를 사용한다는 것입니다 중 하나 = 토큰 또는이 보강 최상위 수준에서 괄호 안의 최상위 수준의 목록. 따라서 sizeof(SomeClass)==4이더라도 M(SomeClass obj(true, 3));은 컴파일되지 않습니다. braced initializers는 괄호 초기화 자와 완전히 동등하지 않기 때문에 일부 선언은 매크로와 함께 사용할 수 없다는 것을 의미합니다.