static_assert

Share the Article

C++11 introduces this new type of assertion which checks an expression at compile time. This is different from regular “assert” statement, which works at runtime. When the expression in static_assert evaluates to value “False” then, it the program will not compile.

In the following example, the compiler executes a function “funda” at compile time and checks if it is returning integer value “1”. Ultimately, the expression fails and compiler throws error.

#include <iostream> //main header using namespace std; //namespace constexpr int funda() { return 0; } int main() { static_assert(funda()==1, "This is not equal"); return 0; }

The output is:

static_assert throws error in compile time in c++11

When compiler cannot check the expression

For static_assert to work properly, the assert condition must be a constant expression. This means, if the compiler is not able to evaluate the expression, then static_assert will not work.

Unlike previous example, now the the function “funda” do not have “constexpr” keyword. Therefore, compiler shall not be able evaluate this anymore.

int funda() //Not constexpr { return 0; }

The output is:

compiler error by calling non-const function in static_assert

Limitation in C++11 with constexpr

In C++11, a constexpr function must be of a single line and that line can be only one return statement. However, this limitation is removed in C++14. Finally, the following function cannot compile in C++11 but will compile in C++14.

#include <iostream> //main header using namespace std; //namespace constexpr int funda() { constexpr int iy = 8; //Line no. 1 return iy; //Line no. 2 } int main() { static_assert(funda() == 1, "This is not equal"); return 0; }

Output in C++11 (compiler error)

static_assert does not work in c++11

Output in C++14 (static_assert failed error)

static_assert works in C++14

Using decltype for templates

Compilers can execute decltype on a template and also deduces its type. However, as the case in above example, the type deduction should be possible during compilation. For example, in following program, the return type of template function “funda” is T and this is clearly deducible by checking return value “tx” type. Here, the template function initialization has argument of type “integer” and therefore same shall be the return type.

#include <iostream> //main header using namespace std; //namespace template<typename T> T funda(T tx) // deduction of T needed { return tx; } int main() { static_assert(is_same<decltype(funda(4)), char> (), "This is not equal"); return 0; }

The output is compiler static_assert fail message:

using decltype in static_assert

Using decltype with reference

Along with the datatype, the decltype keyword also knows if the given type is reference or not. The program can pass decltype’s return value to a template function. In such case, the compiler first instantiate the template with type and then checks if this is a reference. The following program uses the template functions from std namespace, (is_reference etc) with return value of decltype.

#include <iostream> //main header using namespace std; //namespace int main() { int ix = 9; // ix is not a reference int &iy = ix; // iy is a reference int &iz = ix; // iz is l-value reference int &&ia = 4; // ia is r-value reference static_assert(is_reference<decltype(ix)> (), "This is not reference"); static_assert(is_reference<decltype(iy)> () , "This is not reference"); static_assert(is_lvalue_reference<decltype(iz)> () , "This is Lvalue reference"); static_assert(is_rvalue_reference<decltype(ia)> () , "This is Rvalue reference"); return 0; }

Here, only the first static_assert fails because variable ix is not reference and it is_reference return false. The output is:

using decltype with reference in static_assert

Using sizeof( ) at compile-time

Just like, decltype, the compiler can also evaluate sizeof ( ). The advantage with sizeof is that it can also work with a template parameter as argument. In the following program, the parameter T in function template “fun” deduces as integer type. Therefore, sizeof(T) shall return sizeof(int), which is value 4. Everything happens in compile time. Specifically, deduction of argument and execution of sizeof is executed inside static_assert.

#include <iostream> //main header using namespace std; //namespace template<typename T> void funda(T tx) { static_assert(sizeof(tx) != 4, "This is int, if it fails");} int main() { auto ax = 9; fund(ax); return 0; }

The sizeof(integer) != 4 is false, therefore, the compiler generates following error.

using sizeof in static_assert

Another format of static_assert with no message

The static_assert do not require message. The following example, shows how to use this overload.

template<typename T> void funda(T tx) { static_assert(sizeof(tx) != 4); }
static_assert with no message

Using auto return type in static_assert

When a function’s return type is auto then the compiler can deduce the actual type with return statement. The type deduction rules of auto applies.

In following program, the return statement in function “fun” returns the value of type std::string. Therefore, return type “auto” deduces to type std::string. Finally, due to presence of keyword const and ampersand, the return type of function becomes “const std::string&”.

Since, everything happens at compile time and is_same is also template function, therefore, the static_assert works as shown in the output.

#include <iostream> //main header using namespace std; //namespace const auto& funda() { static std::string test{ "hello funda!" }; return test; } int main() { static_assert(std::is_same<decltype(funda()), const std::string&>(), ""); //Pass static_assert(std::is_same<decltype(funda()), const std::string>(), ""); //Fails return 0; }

The output will be straightforward in c++14. The compiler generates following message.

using auto return type with static_assert in C++14

However, in C++11, the auto type deduction for return type cannot happen without trailing return type. Therefore, the compiler throws another error.

using auto return type with static_assert in C++11

To correct this, firstly, the return type should be “auto” and not “const auto&”. Secondly, the trailing return type has to be specified as shown below.

auto funda() -> const std::string& { static std::string test{ "hello funda!" }; return test; }

Main Funda: static_assert makes the compiler to execute code, therefore is more efficient.

Related Topics:

 What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
emplace_back vs push_back

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *