Тест для "POD-ness" в С++/С++ 11?

У меня есть код, который принимает упакованную структуру/класс POD и копирует его в блок памяти.

struct A
{
   int a;
   int b;
} a;

memcpy(mymemoryblock, (void *)&a, sizeof(A));

// later I get a reply and...

memcpy((void *)&a, mymemoryblock, sizeof(A));

Это справедливо только для типов данных POD, и я хотел бы знать, есть ли способ, которым я могу проверить POD-ness. Если кто-то случайно добавляет функцию-член в этот класс, операции memcpy становятся недействительными, но все же компилируемыми. Это приводит к очень трудному обнаружению ошибок.

Есть ли функция is_POD_type (A) или какой-либо другой трюк, который можно использовать для обнаружения PODness во время выполнения или времени компиляции?

Ответ 1

std::is_pod<A>::value в С++ 11.

[Изменить: см. упоминание Люка выше, в С++ 11 вам не нужен тип, который должен быть POD для того, что вы делаете.

В этом случае вам также не нужно бросать на void*, а указатели каста C-стиля на void* без необходимости - это немного рискованно, потому что когда-нибудь вы выбросите const случайно! ]

В С++ 03 нет стандартного способа сделать это, но Boost имеет свой собственный is_pod, который ошибается на стороне осторожности в компиляторах, которые не предоставляют нестандартный способ узнать. Поэтому полезно, если вы пишете код, где особый случай POD - это оптимизация (вы просто не получите оптимизацию везде). Это также полезно, если вы заботитесь только о компиляторах, для которых Boost может получить точный ответ. Это не так хорошо, если ложные отрицания is_pod заставляют ваш код отказаться от отвращения.

Ответ 2

Стандарт (С++ 98) говорит, что только типы с C-подобной конструкцией/деструкцией семантики могут быть членами объединения. Это охватывает большинство вещей, которые могут сделать тип не-POD, поэтому просто определите тип объединения с членом типа A, и компилятор должен жаловаться, если A не является POD.

Ответ 3

Существует метод вызова std:: tr1:: is_pod

Также вы можете использовать bycicle как:

#define CHECK_TYPE_IS_A_POD(TYPE)\
{\
  switch(1)\
  {\
    case 1:\
        TYPE IF_COMPILE_ERROR_THEN__##TYPE##__IS_NOT_A_POD;\
        /* prune out any warnings about not usage */ \
        IF_COMPILE_ERROR_THEN__##TYPE##__IS_NOT_A_POD = TYPE();\
    case 2:\
        ;\
  }\

Но он не работает для имен квалификаций пространства имен и специализированных типов шаблонов.