Как вставить имя типа в виде строки в статический assert ()? [дубликат]

этот вопрос уже есть ответ здесь:

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

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

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

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

2 ответов


невозможно создать требуемую строку во время компиляции и поместить ее в сообщение, но это обычно не проблема на практике, поскольку сообщение об ошибке будет содержать вызывающий контекст, и вы всегда можете создать оболочку для вашего 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 (или вот: std::basic_string<char>) это показали.

живой пример (Лязг)

для GCC сообщение об ошибке также очень приятно:

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" );
     ^

живой пример (GCC)


внутри шаблонов, вы получаете то, что Даниель ФрейС объяснил. Вне шаблонов это невозможно с помощью 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.