Take the 2-minute tour ×

Let's say I have a template function that takes an integer and a const reference to an instance of type T. Now depending on the integer, only some T's are acceptible, otherwise an exception is thrown at runtime.

If all uses of this function would use constant integers, it would be possible to make the int a template parameter and use a static assertion to check if it is acceptable. So instead of func(1,c) one would use func<1>(c) and would gain compile-time type checking. Is there any way to write func(1,c) and still keep the compile-time check, while also being able to write func(i,c) and use a dynamic assertion? The goal is to make it transparent to the developer. It would simply be great to add this safety without bothering the developers about things like compile-time constants. They'd probably only remember that func(1,c) always works and use that, avoiding the check.

How can I define a function with a static assertion whenever possible and a dynamic assertion otherwise?

The following code shows the solution for GCC by Ivan Shcherbakov:

#include <iostream>
#include <cassert>

template<typename T>
void __attribute__((always_inline)) func(const int& i, const T& t);

void compile_time_error_() __attribute__((__error__ ("assertion failed")));

  void __attribute__((always_inline))
  func(const int& i, const float& t)
    do {
        if (i != 0) {
            if (__builtin_constant_p(i)) compile_time_error_();
            std::cerr << "assertion xzy failed" << std::endl;
    } while (0);

This will only allow the combination of i=0 and T=float. For other combinations a good way would be creating a Macro that produces the code of template<> func(const int& i, const T& t) with T and i != 0 replaced.

share|improve this question
static_assert? –  Linuxios Jul 11 '12 at 20:57
@Linuxios static_assert needs a constant-expression. I can do a static assertion without C++11 if I always have a constant-expression. The problem is doing a dynamic assertion otherwise instead of failing to compile. –  Tar Jul 11 '12 at 20:59
I get it! I'll think about that. –  Linuxios Jul 11 '12 at 21:02
I don't think it is possible (or rather, reasonably possible) to write the same expression for compile-time constants and runtime variables. The closest would be the template to accept a compile-time constant integer. –  Xeo Jul 11 '12 at 21:16
@jrok The const reference is simply a promise not to change the value referenced by it, it doesn't guarantee you a constant-expression. So this doesn't work out. –  Tar Jul 11 '12 at 21:30
show 9 more comments

2 Answers

up vote 6 down vote accepted

Well, if you're using GCC, you can use a dirty hack, but it will only work when function inlining is enabled (-O1 or more):

void my_error() __attribute__((__error__ ("Your message here")));

template <typename T1, typename T2> struct compare_types 
    enum {Equals = 0};

template <typename T1> struct compare_types<T1,T1> 
    enum {Equals = 1};

template <typename Type> __attribute__((always_inline)) void func(int a, Type &x)
    if (__builtin_constant_p(a))
        if (a == 1 && compare_types<Type,char>::Equals)

In this case when a == 1 and Type is char, you'll get an error. Here's an example that will trigger it:

int main()
    char x;
    func(1, x);
    return 0;

Note that this example heavily relies on the gcc-specific __builtin_constant_p() function and won't work with other compilers!

share|improve this answer
Ah, this is great! Is there a similar function for clang? –  Tar Jul 11 '12 at 21:57
Quickly googling for "__builtin_constant_p LLVM" says "no", but maybe you will be more lucky. It's heavily used in fcntl2.h, so I would look there to see how LLVM handles it. –  Ivan Shcherbakov Jul 11 '12 at 22:33
Didn't research, but using it with clang++ succeeded here. –  Benjamin Bannier Jul 11 '12 at 22:36
clang.llvm.org/docs/LanguageExtensions.html#builtins says that clang supports __builtin_constant_p, so this solution is nearly perfect. I doubt it's possible in a portable manner. –  Tar Jul 12 '12 at 5:44
Don't use reserved names like _Type and __my_error. –  Xeo Jul 14 '12 at 7:27
show 1 more comment

Let me paraphrase question to be more accurate in my answer:

Can runtime assert sometimes report errors on compile time.

Gcc can, but only on some optimization level and error message is very uninformative. Clang itself can't (no error attribute), but do not forget about clang analyzer. Analyzer can report some runtime errors like dereferencing null pointer.

So here is an idea and simple test of 'smart' runtime assert:

#include <cstdlib> // std::abort

#if !defined(__clang__) && defined(__GNUC__)
// clang emulates gcc
# define GCC_COMPILER 1
# define GCC_COMPILER 0

void assertion_failed_message() __attribute__((__error__("assertion failed")));

inline void smart_assert(bool condition) {
  // gcc is very 'sensitive', it must be first code lines in this function
  if (__builtin_constant_p(condition) && !condition) {

  if (condition) {
    // Ok

#if defined(__clang_analyzer__)
  enum {
    ASSERTION_FAILED = 0xdeadfull
  int *a = nullptr;

  // Implement some standart error, like abort

void test_condition_2(bool condition) {

void test_condition_1(bool condition) {

void test_condition_0(bool condition) {

int main() {
  return EXIT_SUCCESS;

Gcc report error at O2 optimization level, it's good. But report message is in main function, and don't leave any information about test_condition_{0,1,2}.

Clang analyzer report error and if you use Xcode, you can see all path from main to smart_assert: clang_analyzer_report

P.S. clang analyzer is not perfect, so if you try test_condition_0(argc), no error will be reported (truely runtime check), but if you try test_condition_0(argc==1), false positive will be reported.

share|improve this answer
This might be "smart" but it's also disgusting. +1 anyway, but ... eurgh. –  Jonathan Wakely Oct 4 at 22:51
@JonathanWakely The only one disgusting thing I see here is that analyzer can report false positives)) –  ruslo Oct 6 at 16:48
add comment

Your Answer


