4

This code demos a compile time assert using template. I found it can only be compiled by g++ (4.4.7) with the following cmd line.

$ g++ -std=c++98 a.cpp -o a

Nether icc (13.0.1) nor visual c++ (14.00.50727.762 for 80x86) can compile it. For icc, it generate error msg like this

$ icpc a.cpp -o a
a.cpp(13): error: non-integral operation not allowed in nontype template argument
      COMPILE_TIME_ASSERT(true && "err msg");
      ^

a.cpp(13): error: class "CompileTimeAssert<<error-constant>>" has no member "Check"
      COMPILE_TIME_ASSERT(true && "err msg");
      ^

compilation aborted for a.cpp (code 2)

However I found assertions like true && "err msg" are widely used in run-time assert as Add custom messages in assert?

Questions are

  1. Can this be solved without modifying the code, only with proper compile options?
  2. If can't, any alternative methods of compile time assert with custom messages?

Demo code show as follows.

#include <iostream>

template<bool B> class CompileTimeAssert { };
template<> class CompileTimeAssert<true> {
 public:
  static inline void Check() { }
};

#define COMPILE_TIME_ASSERT(b) CompileTimeAssert<(b)>::Check()

int main()
{
    COMPILE_TIME_ASSERT(true && "err msg");
    std::cout<<(true && "err msg")<<std::endl;
    return 0;
}
Community
  • 1
  • 1
kangshiyin
  • 9,681
  • 1
  • 17
  • 29

1 Answers1

0

Answer to the first question is "No". An argument you pass to the template is so called "non-type template argument". According to the standard, such arguments must be:

constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.

An expression like true && "err msg" strictly speaking cannot be determined at compile time. That's why it can be used with run-time assertions but not in compile-time ones. G++ demonstrates here non-standard behaviour.

As an answer to the second question, I propose the following pattern:

#define STATIC_ASSERT(e,m) extern char (*__static_assert_failed(void)) [ 1 - 2*!(e) ] 

__static_assert_failed here is a pointer to external function returning an array of chars. The array has size of 1 - 2*!(e) which became negative if e is false causing compile-time error.

Yury Bayda
  • 1,023
  • 1
  • 9
  • 20