C ++: как использовать type_traits, чтобы определить, тривиален ли класс? - PullRequest
8 голосов
/ 02 октября 2011

В C ++ 0x я хотел бы определить, является ли класс тривиальным / имеет стандартную разметку, чтобы я мог использовать memcpy (), memset () и т. Д. *

Как мне реализоватькод ниже, используя type_traits, так что я могу подтвердить, что тип тривиален?

template< typename T >
bool isTrivialType()
{
  bool isTrivial = ???
  return isTrivial;
}

ПРИМЕЧАНИЕ: is_pod () слишком ограничительный: я хотел бы, чтобы мой класс имел тривиальные конструкторы и т.д ... ...для удобства.

Добавлено: Я думаю, что std :: is_standard_layout <> может дать мне то, что я ищу.1. Если я добавляю конструкторы, он по-прежнему возвращает true. 2. Если я добавляю виртуальный метод, он возвращает false. Это то, что мне нужно, чтобы определить, могу ли я использовать memcpy (), memset ()

Edit: FromОбъяснение и ссылка Люка Дантона ниже (уточнение):

struct N { // neither trivial nor standard-layout
   int i;
   int j;
    virtual ~N();
};

struct T { // trivial but not standard-layout
    int i;
private:
    int j;
};

struct SL { // standard-layout but not trivial
    int i;
    int j;
    ~SL();
};

struct POD { // both trivial and standard-layout
    int i;
    int j;
};

Для того, чтобы memcpy () был счастлив:

// N -> false
// T -> true
// SL -> ??? (if there are pointer members in destructor, we are in trouble)
// POD -> true

Так что выглядит как is_trivial_class <> правильно: is_standard_layout <>не обязательно прав ...

Ответы [ 2 ]

6 голосов
/ 02 октября 2011

Для std::memcpy достаточно, чтобы тип был тривиально копируемым.Начиная с n3290, 3.9 Типы [basic.types] параграф 2:

Для любого объекта (кроме подобъекта базового класса) тривиально копируемого типа T, независимо от того, содержит ли объект допустимое значениетип T, лежащие в основе байты (1.7), составляющие объект, могут быть скопированы в массив char или unsigned char.

В следующих параграфах также описаны другие полезные свойства тривиально копируемых типов (т.е. не просто копирование)в массив char).

std::is_trivially_copyable - это черта, позволяющая обнаружить именно это.Однако на момент написания этой статьи он не реализован, например, GCC, поэтому вы можете использовать std::is_trivial в качестве запасного варианта (поскольку, в свою очередь, для этого требуется простой конструктор копирования).

Я действительно не рекомендую использовать is_standard_layout если вы действительно не знаете, что делаете (например, взаимодействие языков на одной конкретной платформе), это не то, что вам нужно. Дополнительная информация о том, какие тривиальности и стандартная схема могут помочь вам определить точные требования, которые вы хотите.

1 голос
/ 02 октября 2011

Определение POD в C ++ 11:

Структура POD - это класс, не являющийся объединением, который является как тривиальным классом, так и классом стандартной компоновки и не имеетстатические данные-члены типа non-POD struct, non-POD union (или массив таких типов).

Так что, если вы не нарушаете правила стандартного макета или что-то в этом роде, is_podдолжно быть достаточно.А если вы нарушаете правила стандартного макета, вы не можете использовать memcpy и memset и т. Д.

Так что я не знаю, зачем вам это нужно, если вы не пытаетесь проверитьмелочь конкретно.

...