Почему предпочтение статического утверждения на основе шаблона статическому утверждению на основе определения типа? - PullRequest
8 голосов
/ 05 августа 2011

Существует две широко используемые реализации статического утверждения для версий C ++, которые не имеют встроенной static_assert.

Первый используется в Boost и использует шаблон и специализацию этого шаблона :

template <bool> struct static_assert;
template <> struct static_assert<true> {}; // only true is defined
#define  STATIC_ASSERT(x) static_assert<(x)>()

Здесь, когда условие для проверки ложно, компилятор не может найти универсальную версию шаблона, и компиляция не удалась.

второй использует typedef:

#define STATIC_ASSERT( x ) typedef char __STATIC_ASSERT__[( x )?1:-1]

Здесь, когда условие для проверки нарушается, компилятор пытается typedef массив размера -1, и это недопустимо, следовательно, ошибка времени компиляции.

Для меня последний вариант лучше, поскольку он гарантированно не генерирует код, а также может использоваться следующим образом (с здесь ):

template<int Shift> class BinaryFlag {
    STATIC_ASSERT( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
    public:
    static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue

пока первое не может быть использовано таким образом.

Есть ли какая-либо причина предпочитать первую реализацию static assert второй?

Ответы [ 2 ]

4 голосов
/ 05 августа 2011

Вторая версия STATIC_ASSERT вы не можете использовать одну за другой в одном и том же блоке.

template<int N, int M>
void foo ()
{
  STATIC_ASSERT(N<M), STATIC_ASSERT(M<0);  // error
};

Демо .

С другой стороны, вНапример, вы разместили, вы не можете использовать первую версию (потому что она имеет дело с временными конструкциями).Так что обе версии имеют свою аудиторию.Первая версия, которую я могу сказать, является своего рода смесью компиляции и среды выполнения.Однако 2-я версия является просто временем компиляции.

Редактировать : иногда для удобства чтения вы можете поместить все утверждения в одну строку с помощью оператора comman (где в этом случае будет действовать только последняя инструкция).Я знаю, что их тоже можно поставить с ;.Но только для примера, это один из вариантов использования.

Точно так же будут ситуации, когда конструкция объекта будет в порядке, но синтаксически установка typedef не будет в порядке.Так что все они упадут в одно и то же место.

2 голосов
/ 05 августа 2011

Я обычно использовал второй или какой-то другой вариант в своем собственном коде.На практике вариант Boost имеет то преимущество, что его можно использовать везде, где может появляться выражение, а не только на уровне операторов.У него есть недостаток, заключающийся в том, что его можно использовать только там, где может появиться выражение, и, следовательно, за пределами области имен.

...