2014-01-03 2 views
7

ПроблемаКак вставить имя типа в виде строки в static_assert()?

Следующая не строит, потому что сообщение не является строкой литерала.

template<typename T> 
struct Foo 
{ 
    Foo() 
    { 
    static_assert(is_pod<T>::value, typeid(T).name()); 
    } 
}; 

В конечном счете, я хотел бы сообщение об ошибке, как «Бар должен быть под-типа», если я пытаюсь скомпилировать Foo<Bar> fb;.

Возможно ли построить эту строку во время компиляции, как требуется static_assert?

+0

Составление строки во время компиляции - вы можете сделать это с помощью некоторых грязных макросов или магии шаблонов. [См. Здесь] (http://stackoverflow.com/q/6002594/183120) для чего-то подобного. – legends2k

ответ

5

Невозможно построить нужную строку во время компиляции и поместить ее в сообщение, но на практике это обычно не проблема, так как сообщение об ошибке будет содержать вызывающий контекст, и вы всегда можете создать оболочку для ваш static_assert, который показывает тип в сообщении об ошибке:

template< typename T > 
void verify_pod() 
{ 
    static_assert(std::is_pod<T>::value, "T is not a POD"); 
} 

дающий

clang++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out 
main.cpp:7:5: error: static_assert failed "T is not a POD" 
    static_assert(std::is_pod<T>::value, "T is not a POD"); 
    ^   ~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:12:5: note: in instantiation of function template specialization 'verify_pod<std::basic_string<char> >' requested here 
    verify_pod<std::string>(); 
    ^
1 error generated. 

Обратите внимание на note: ... где обертка с типом std::string (о r здесь: std::basic_string<char>).

Live example (Clang)

Для НКУ, сообщение об ошибке также очень приятно:

main.cpp: In instantiation of 'void verify_pod() [with T = std::basic_string<char>]': 
main.cpp:12:31: required from here 
main.cpp:7:5: error: static assertion failed: T is not a POD 
    static_assert(std::is_pod<T>::value, "T is not a POD"); 
    ^

Live example (GCC)

+0

Обратите внимание, что g ++ propably не даст такого приятного сообщения об ошибке. – arne

+2

@arne Не правда. На самом деле сообщение GCC об ошибке еще лучше (IMHO). –

+0

У нас, похоже, очень разные идеи хороших сообщений об ошибках.В вашем случае это может выглядеть нормально, но если у вас много шаблонов, выход g ++ становится практически нечитаемым imho. Тем не менее, ваш ответ правильный. – arne

2

Внутри шаблонов, вы получите то, что Daniel Frey «s имеет explained. Внешние шаблоны, это не представляется возможным с только static_assert, но может быть достигнуто с помощью макроса и оператора stringification #:

#define VERIFY_POD(T) \ 
    static_assert(std::is_pod<T>::value, #T " must be a pod-type"); 

Для типа struct non_pod { virtual ~non_pod() {} }; с GCC 4.8.1, VERIFY_POD(non_pod) дает

main.cpp:4:2: error: static assertion failed: non_pod must be a pod-type 
    static_assert(std::is_pod<T>::value, #T " must be a pod-type"); 
^
main.cpp:15:2: note: in expansion of macro 'VERIFY_POD' 
    VERIFY_POD(non_pod); 

Если вы похожи на меня и не хотите, чтобы увидеть маркеры #T " must be a pod-type" в сообщении об ошибке, то вы можете добавить дополнительную строку к макроопределению:

#define VERIFY_POD(T) \ 
    static_assert(std::is_pod<T>::value, \ 
    #T "must be a pod-type"); 

с этим, предыдущий пример дает:

main.cpp: In function 'int main()': 
main.cpp:4:2: error: static assertion failed: non_pod must be a pod-type 
    static_assert(std::is_pod<T>::value, \ 
^
main.cpp:14:2: note: in expansion of macro 'VERIFY_POD' 
    VERIFY_POD(non_pod); 
^

Конечно, точный вид сообщения об ошибке зависит от компилятора. С clang 3.4 мы получаем

main.cpp:14:5: error: static_assert failed "non_pod must be a pod-type" 
    VERIFY_POD(non_pod); 
    ^~~~~~~~~~~~~~~~~~~ 

main.cpp:3:23: note: expanded from macro 'VERIFY_POD' 
#define VERIFY_POD(T) \ 
        ^
1 error generated. 
+1

Я не думаю, что это может работать с шаблонами, как в OP. Я имею в виду, он выведет имя параметра шаблона, если я не ошибаюсь. – dyp

+0

@DyP Действительно, это работает лучше внешних шаблонов. Внутри шаблонов он «работает» так же, как в [Daniel Frey] (http://stackoverflow.com/users/2073257/daniel-frey) [ответ] (http://stackoverflow.com/a/20903339/ 1137388). –

+0

@DyP Я обновил сообщение, чтобы прояснить этот момент. Благодарю. –

Смежные вопросы