N
Niklas Norrthon
I just want to share a technique I discovered when playing
around with templates. It is a simple idea, so I doubt I
am first, perhaps it's even used in the standard library
implementations, and the boost library.
Anyway, the idea is to use templates as a compile time
assert, letting the compiler fail, with a reasonable
diagnostics if some condition isn't fulfilled.
For example, consider a template function that shifts
variables of the template argument type left and right,
then it would be nice to assure that the template
argument time isn't signed, since right shifting isn't
well defined on negative values:
template <typename IntType>
IntType func(IntType x)
{
/* do operations on x */
x >>= 1; /* what if x < 0? */
return x;
}
My solution is this:
#include "compile_assert.h"
#include <limits>
template <typename IntType>
IntType func(IntType x)
{
compile_assert< ! std::numeric_limits<IntType>::is_signed > ();
/* do operations on x */
x >>= 1; /* what if x < 0? */
return x;
}
The code result in a compiler diagnostic pointing to the compile_assert
line if the function is called with a signed type argument.
Here is the definition of compile_assert:
#ifndef H_COMPILE_ASSERT
#define H_COMPILE_ASSERT
namespace {
template <bool is_ok> struct compile_assert_t;
template <> struct compile_assert_t<true> { };
}
template <bool is_ok> void compile_assert()
{
compile_assert_t<is_ok>();
}
#endif
No question just wanted to share, comments are welcome.
/Niklas Norrthon
around with templates. It is a simple idea, so I doubt I
am first, perhaps it's even used in the standard library
implementations, and the boost library.
Anyway, the idea is to use templates as a compile time
assert, letting the compiler fail, with a reasonable
diagnostics if some condition isn't fulfilled.
For example, consider a template function that shifts
variables of the template argument type left and right,
then it would be nice to assure that the template
argument time isn't signed, since right shifting isn't
well defined on negative values:
template <typename IntType>
IntType func(IntType x)
{
/* do operations on x */
x >>= 1; /* what if x < 0? */
return x;
}
My solution is this:
#include "compile_assert.h"
#include <limits>
template <typename IntType>
IntType func(IntType x)
{
compile_assert< ! std::numeric_limits<IntType>::is_signed > ();
/* do operations on x */
x >>= 1; /* what if x < 0? */
return x;
}
The code result in a compiler diagnostic pointing to the compile_assert
line if the function is called with a signed type argument.
Here is the definition of compile_assert:
#ifndef H_COMPILE_ASSERT
#define H_COMPILE_ASSERT
namespace {
template <bool is_ok> struct compile_assert_t;
template <> struct compile_assert_t<true> { };
}
template <bool is_ok> void compile_assert()
{
compile_assert_t<is_ok>();
}
#endif
No question just wanted to share, comments are welcome.
/Niklas Norrthon