2013-02-11 3 views
6

문자열 리터럴이 아닌 다른 것에 안정적으로 static_assert하려면 어떻게해야합니까?type_traits를 사용하여 문자열 리터럴을 검색하는 방법은 무엇입니까?

예를 들어 다음 코드에서 나는 표준 어설 션 매크로를 래핑하려고 시도했지만 문자열 리터럴이 아닌 메시지에 대해서는 아무것도 거부합니다 (런타임시 문자열 리터럴이 표시되지 않기 때문에 어설트 트리거).

#include <cassert> 
#include <string> 
#include <type_traits> 

#define my_assert(test, message)\ 
    static_assert(\ 
     (\ 
      !std::is_pointer<decltype(message)>::value &&\ 
      !std::is_array<decltype(message)>::value\ 
     ),\ 
     "literal string required"\ 
    );\ 
    assert((message, (test))); 

int main() { 
    my_assert(1 == 1, "one equals one"); 
    my_assert(1 == 2, "one equals two"); 

    { 
     const char *msg = "one equals one"; 
     //my_assert(1 == 1, msg); // triggers static_assert 
    } 

    { 
     const char msg[] = "one equals one"; 
     //my_assert(1 == 1, msg); // triggers static_assert 
    } 

    { 
     const std::string msg = "one equals one"; 
     //my_assert(1 == 1, msg.c_str()); // triggers static_assert 
    } 

    { 
     const int msg = 3; 
     my_assert(1 == 1, msg); // should trigger static_assert 
    } 
} 

당신이 볼 수 있듯이

는 시험이 코드는 의도 한대로 (GCC 4.7.2 테스트) 작동, 대부분 을 type_traits 헤더가 제공하는 테스트를 통해 수행하고있다. 그러나 프로그래머가 사용할 수있는 일반적인 것들을 거부하는 것만 큼 문자열 리터럴을 특별히 찾지 않습니다.

위의 예제에서는 해결책이 충분하지만 다른 상황에서도 이와 비슷한 기술을 사용하고 싶습니다.

그렇다면 어떻게 안정적으로 type_traits (또는 다른 표준 메커니즘)를 static_assert에 사용합니까? 문자열 리터럴을 제외하고 무엇입니까? 여기

+0

실제로 어설 션이 실패 할 때 메시지를 표시 하시겠습니까? 그렇다면 다른 질문을 게시하십시오. 표준'assert()'매크로는 제 의견으로는 쓸모가 없지만 실제로 변수를 작성하여 변수의 값과 함께 메시지를 표시하는 방법은 정말 멋집니다. – Ali

+0

@Ali 감사합니다.하지만 제 질문은 질문에 대한 대답이 유용 할 수있는 한 가지 이유를 설명하는 동기 부여 수단이었을뿐 아니라 'assert()'와는 거의 관련이 없습니다. assert가 gcc/libc가 제공하는 표준을 사용하지 못하면 큰 메시지를 받는다. 물론 정교화 된 방법을 사용하여 단언 할 수는 있지만 사실은 제 질문의 핵심은 아닙니다. 제가 말했듯이 저는 문자열 리터럴과 다른 것을 감지하는 방법에 관심이 있습니다. (내 자신의 대답은 트릭을 꽤 가깝게하는 것 같습니다.) – wjl

+0

좋아, 나는 당신이 멋진 주장이 필요했지만. 글쎄, 행운을 비네! – Ali

답변

5

내가 그것을 던질 것을 거부 나타나는, 내가 할 수있는 최선이지만, 여전히 리터럴 문자열 허용합니다

#define my_assert(test, message)\ 
    static_assert(\ 
     (\ 
      std::is_convertible  <decltype(message), const char *>::value &&\ 
      !std::is_rvalue_reference <decltype(message)>::value &&\ 
      !std::is_pointer   <decltype(message)>::value &&\ 
      !std::is_array   <decltype(message)>::value &&\ 
      !std::is_class   <decltype(message)>::value\ 
     ),\ 
     "string literal required"\ 
    );\ 
    assert((message, (test))) 

나는이 실제로가 철저 있는지 알고 매우 싶네을 정확하고, 그리고/또는이 탐지를 수행하는 더 간단한 방법이 있다면.

0

'문자열 리터럴의 decltype ("some string")'은 "const char (&) [n]"유형을 반환합니다. 는 따라서, the following answer에 비해, 더 간결가 보인다, 방법은 그것을 감지 :

template<typename T> 
struct IsStringLiteral : 
    std::is_same< 
     T, 
     std::add_lvalue_reference_t<const char[std::extent_v<std::remove_reference_t<T>>]> 
    > 
{}; 

(online demo)

관련 문제