Я читаю библиотеку машинного обучения dlib, написанную на C ++. Я наткнулся на код в заголовочный файл который определяет кучу макросов. У меня трудности с пониманием следующего кода
#ifndef BOOST_JOIN
#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)
#define BOOST_DO_JOIN2( X, Y ) X##Y
#endif
// a bunch of other code
namespace dlib
{
template <bool value> struct compile_time_assert;
template <> struct compile_time_assert<true> { enum {value=1}; };
// a bunch of other definitions
}
#define COMPILE_TIME_ASSERT(expression) \
DLIB_NO_WARN_UNUSED typedef char BOOST_JOIN(DLIB_CTA, __LINE__)[::dlib::compile_time_assert<(bool)(expression)>::value]
что я не понимаю, так это
что делает последняя строка в приведенном выше коде?
typedef char
вот так странно, я вообще этого не понимаю.
BOOST_JOIN
, это становится DLIB_CTA__LINE__[1]
зачем это массив? Это законно?Это статическое утверждение C ++ 03 или, по крайней мере, обходной путь, используемый для его моделирования.
Следующее определяет структуру, только если value
верно, иначе тип не определен.
template <bool value> struct compile_time_assert;
template <> struct compile_time_assert<true> { enum {value=1}; };
Что значит compile_time_assert<true>::value
совершенно правильно, но compile_time_assert<false>::value
это ошибка компиляции, так как compile_time_assert<false>
не определено.
Теперь суть утверждения:
DLIB_NO_WARN_UNUSED typedef char BOOST_JOIN(DLIB_CTA, __LINE__) ::dlib::compile_time_assert<(bool)(expression)>::value]
Это определяет typedef на char
массив размером 1, только если expression
оценивает как истинное. Если выражение оценивается как ложное, то возникает ошибка времени компиляции и имя typedef является подсказкой об ошибке.
Обратите внимание, что есть несколько вариантов этого. Некоторые используют отрицательный или нулевой размер вместо ошибки компиляции, т.е. они определяют следующее:
template <> struct compile_time_assert<false> { enum { value = -1 }; };
Но на самом деле есть способ краткой формулировки этого (вы можете увидеть это в этом вопросе):
typedef char static_assert_something[expression ? 1 : -1];