0

I am reading the machine learning library dlib which is written in C++. I came across a code in a header file which defines a bunch of macros. I have difficulties understanding the following code

#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] 

what I do not understand is that

  1. what does the last line in the above code do?

  2. typedef char here is so weird, I don't understand it at all.

  3. After substitution for BOOST_JOIN, it becomes DLIB_CTA__LINE__[1], why it is an array? Is it legal?
Davis King
  • 4,731
  • 1
  • 25
  • 26
Allanqunzi
  • 3,230
  • 1
  • 26
  • 58

1 Answers1

3

This is a C++03 static assert, or at least the workaround used to simulate it.

The following defines a struct only if value is true, else the type is not defined.

template <bool value> struct compile_time_assert;
template <> struct compile_time_assert<true> { enum {value=1};  };

Which means compile_time_assert<true>::value is perfectly correct, but compile_time_assert<false>::value is a compilation error since compile_time_assert<false> is not defined.

Now, the core of the assert:

DLIB_NO_WARN_UNUSED typedef char BOOST_JOIN(DLIB_CTA, __LINE__) ::dlib::compile_time_assert<(bool)(expression)>::value]

This defines a typedef on a char array of size 1, only if expression evaluates to true. If the expression evaluates to false, then there is a compile time error and the name of the typedef is a hint about the error.

Note that there are some variants of this. Some use a negative or null size instead of a compilation error, ie they define the following:

template <> struct compile_time_assert<false> { enum { value = -1 };  };

But actually there is a way concise formulation of this (you can see it in this question):

typedef char static_assert_something[expression ? 1 : -1];
Community
  • 1
  • 1
Synxis
  • 9,236
  • 2
  • 42
  • 64
  • Thanks for replying. What does `DLIB_NO_WARN_UNUSED` do here between `COMPILE_TIME_ASSERT(expression)` and `typedef`? – Allanqunzi Apr 08 '15 at 19:34
  • Probably something compiler specific to disable the warning about unused typedef (because you normally won't use this typedef, and some compilers warn about it). – Synxis Apr 08 '15 at 19:44
  • but dlib is the library name, so putting `DLIB_NO_WARN_UNUSED` between `COMPILE_TIME_ASSERT(expression)` and `typedef`, I don't understanding how it is syntactically right. – Allanqunzi Apr 08 '15 at 20:02
  • `DLIB_NO_WARN_UNUSED` is a macro. It could be `#define DLIB_NO_WARN_UNUSED` (so this would be replaced by nothing) or `#define DLIB_NO_WARN_UNUSED some-compiler-magic`. – Synxis Apr 08 '15 at 20:22