Использовать static_assert для проверки типов, переданных макросу

У меня, к сожалению, осталось несколько макросов из исходной версии моей библиотеки, которые использовали довольно сумасшедшие C. В частности, у меня есть серия макросов, которые ожидают, что некоторые типы будут переданы им. Возможно ли сделать что-то по строкам:

static_assert(decltype(retval) == bool);

И как? Есть ли какие-нибудь умные альтернативы?

Да, я знаю, что макросы плохи. Я знаю, что С++ не является C и т.д.

Update0

Вот несколько связанный код, а исходный файл. Предложения приветствуются. Исходный вопрос остается тем же.

Ответы

Ответ 1

Я нашел это самым чистым, используя @UncleBens предложение:

#include <type_traits>

static_assert(std::is_same<decltype(retval), bool>::value, "retval must be bool");

Ответ 2

Кажется, вам нужно decltype, потому что у вас есть выражение, но вы хотите проверить тип. Уже есть достаточно способов сделать это сейчас (С++ 03). Например, чтобы проверить bool

inline void mustBeBool(bool) { }
template<typename T> inline void mustBeBool(T t) { & (&t); } // Takes address of rvalue (&t)

// Use:
#define DifficultMacro(B) do { mustBeBool(B); foo(B); } while (false)

Ответ 3

Отказ от ответственности: это плохой ответ, есть, безусловно, гораздо лучшие решения. Пример:)

Он должен быть уже реализован, но тривиально реализовать себя;

template <class T1, class T2> struct CheckSameType; //no definition
template <class T> struct CheckSameType<T,T>{}; //

template <class T1, class T2>
AssertHasType(T2)
{
   CheckSameType<T1, T2> tmp; //will result in error if T1 is not T2
}

Используется следующим образом:

AssertHasType<bool>(retval);

Альтернатива (предлагается GMan):

template <class T1, class T2> struct SameType
{
    enum{value = false};
}
template <class T> struct SameType<T,T>
{
    enum{value = true};
}; 

Используется как

static_assert(SameType<decltype(retval), bool>::value);

Ответ 4

Большинство макросов можно заменить функциями inline и/или шаблонами. В качестве примера, чрезмерно умный макрос Posix isnan, определяющий размер аргумента, является шаблоном в С++ 0x. О, плохой пример, но вы поняли идею.

Основными исключениями для этого правила являются макросы, которые существенно реализуют языковые функции более высокого уровня. Например, умная обработка исключений или ковариация или параметризованный набор объявлений.

В некоторых случаях макросы, которые не могут быть разумными, выраженные в виде inline функций или шаблонов, могут быть заменены более умным видом предварительной обработки, а именно генерации кода. Тогда у вас есть script, где генерируется необходимый код. Например, можно использовать классы опций в чистом С++ с макросами и шаблонами, но это волосатое, а в качестве более простой и, возможно, более удобной альтернативы можно использовать script, который генерирует требуемые классы за счет стоимости дополнительных шагов сборки и работы с несколькими языками.

Приветствия и hth.,