Static Assert для проверки постоянной времени компиляции НЕ передается в макрос

Преамбула:

switch(nValue)
{
case X:
...
case Y:
...
default:
ASSERT_FOR_DEFAULT(nValue);
}

ASSERT_FOR_DEFAULT является макросом, который отображает (пользовательское) диалоговое окно подтверждения, чтобы сообщить о попадании в «default-case». Да, этот макрос предназначен для подтверждения времени выполнения, а не для утверждения времени компиляции. Но мне просто нужно, чтобы любое постоянное значение (время компиляции) не могло быть передано этому макросу.

Проблема:

Следует потерпеть поражение при компиляции:

ASSERT_FOR_DEFAULT(5);

Да, программист может использовать его где угодно, а не только в default случай switch-case, Он также может использовать любое выражение, которое не используется в switch, Но это не проблема. Просто нужно, чтобы в этот макрос передавалась только непостоянная величина.

Для этого макроса не написано ничего важного, просто предположим, что это ASSERT/assert,

Я пробовал с шаблонами (использовал их другие SFINAE / static-asserts!), Массивы (как strcpy_s), собственная структура, имеющая YES, NO типы, а что нет. Но не смог найти решение!

Я использую VC2008. Я в курсе static_assert, decltype и т.д., но не может использовать C ++ 0x.


РЕДАКТИРОВАТЬ (решение):

#define STATIC_ASSERT(expr) {int array[!!(expr)]; expr;}

template <class T>
bool noConstAllowed(T&);

int noConstAllowed(...);

#define ASSERT_FOR_DEFAULT_VALUE(val)                \
{                                                  \
STATIC_ASSERT(sizeof(noConstAllowed(val))==sizeof(bool));   \
}

int main()
{
int test=10;

ASSERT_FOR_DEFAULT_VALUE(test);
ASSERT_FOR_DEFAULT_VALUE(2);
ASSERT_FOR_DEFAULT_VALUE(test+2);  //FAILS, but okay for me!
}

Спасибо Арне Мерц за это прекрасное предложение. Я вывел решение из этого.
noConstAllowed перегружен для всех T& типы, и если константное значение передается, вызывается другая перегрузка. Оба имеют разные типы возвращаемых значений, и, следовательно, сверяются с размером. Шаблонная версия возвращает bool, который удовлетворяет утверждению для любой передаваемой переменной и завершается неудачей для любой константы или выражения (поскольку возвращаемый тип будет int).

3

Решение

Вы можете переопределить макрос так, чтобы он принимал адрес параметра — что не должно работать для литералов. Однако это не помешает вам передать постоянную переменную, например,

const static int FIVE = 5;
ASSERT_FOR_DEFAULT(FIVE); // still works.

Запрещать все виды констант, передаваемых в ваш макрос, вызывают функцию, которая принимает параметр по неконстантной ссылке:

template <class T>  void noConstAllowed(T&){};
#define ASSERT_FOR_DEFAULT_VALUE(val)                \
{                                                  \
(void*)&(val);         /* no literals*/          \
noConstAllowed(val);   /* no constants at all */ \
switchHitDefaultDialog(val, __FILE__, __LINE__); \
}

Я полагаю, вы используете что-то вроде ФАЙЛ или другие позиционные макросы, или вы бы сделали это функцией. Вам нужно использовать только одну из двух строк.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]