Reputation: 471
I am going through the first chapters of the book "Modern C++ Design". In particular, compile time assertions. I have some problem with the following code:
template<bool> struct CompileTimeChecker
{
CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)\
{\
struct ERROR_##msg {ERROR_##msg() {}};\
CompileTimeChecker<((expr) != 0)>(ERROR_##msg());\
}
int main()
{
STATIC_CHECK(0, MessageNull);
STATIC_CHECK(1, MessageOne);
}
This doesn't raise a compile time error for g++ 7.4.0 and clang++ 6.0.0. However, the following code does raise an error (as expected):
template<bool> struct CompileTimeChecker
{
CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)\
{\
struct ERROR_##msg {ERROR_##msg(int i) {i;}};\
CompileTimeChecker<((expr) != 0)>(ERROR_##msg(0));\
}
int main()
{
STATIC_CHECK(0, MessageNull);
STATIC_CHECK(1, MessageOne);
}
The only difference in the second code is the usage of a constructor with parameters.
The expected error message in both cases is:
no matching function for call to ‘CompileTimeChecker<false>::CompileTimeChecker(main()::ERROR_MessageNull)
no matching conversion for functional-style cast from 'ERROR_MessageNull' to 'CompileTimeChecker<(0 != 0)>'
Upvotes: 2
Views: 143
Reputation: 20569
This is called the most vexing parse. The following statement:
CompileTimeChecker<expr>(Type());
is equivalent to
CompileTimeChecker<expr> Type();
which declares a function named Type
. You can work around the issue by using the =
form of initialization:
CompileTimeChecker<expr> var = Type();
This way, it cannot be interpreted as a declaration. You can also use the {}
initialization since C++11. On the other hand,
CompileTimeChecker<expr>(Type(0));
is an expression statement that creates an object as desired because Type(0)
cannot possibly declare a function.
Since C++11, just use static_assert
.
Upvotes: 5