Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this "call" to assert seeing two arguments instead of just the one?

Given this test program:

#include <cassert>
#include <string>
#include <type_traits>

const std::string& const_string = "bla";
std::string const & string_const = "blabla";

static_assert(std::is_same<decltype(const_string), decltype(string_const)>::value, "Uhoh");

int main()
{
    assert(std::is_same<decltype(const_string), decltype(string_const)>::value);
}

Which asserts that two types are the same at compile-time and at runtime using C's assert. All of Clang, MSVC2015, and GCC report the same error, so I'm quite sure it's me:

main.cpp:13:49: error: too many arguments provided to function-like macro invocation
    assert(std::is_same<decltype(const_string), decltype(string_const)>::value);
                                                ^
/usr/include/assert.h:91:10: note: macro 'assert' defined here
# define assert(expr)                                                   \
         ^

I'm just not seeing two arguments in the assert. What's more, the static_assert works just fine... So what is going on here?

like image 228
rubenvb Avatar asked Mar 10 '16 12:03

rubenvb


People also ask

How does assert work?

The assert() function tests the condition parameter. If it is false, it prints a message to standard error, using the string parameter to describe the failed condition. It then sets the variable _assert_exit to one and executes the exit statement. The exit statement jumps to the END rule.

What does assert mean in C?

In the C Programming Language, assert is a macro that is designed to be used like a function. It checks the value of an expression that we expect to be true under normal circumstances. If expression is a nonzero value, the assert macro does nothing.

How do you assert in CPP?

Assertions in C/C++ Following is the syntax for assertion. void assert( int expression ); If the expression evaluates to 0 (false), then the expression, sourcecode filename, and line number are sent to the standard error, and then abort() function is called.


Video Answer


1 Answers

The C preprocessor does not recognise C++ template syntax, therefore template brackets < and > are not viewed as grouping tokens by the preprocessor, they're seen as simple characters.

This means that the preprocessor will view the comma between the template parameters as a macro parameter separator, like this:

assert(
    std::is_same<decltype(const_string),
    decltype(string_const)>::value);

To force the preprocessor to see your expression as a single statement, simply wrap your assert parameter in an additional set of brackets:

assert((std::is_same<decltype(const_string), decltype(string_const)>::value));

static_assert doesn't have this limitation because it is a C++ keyword, rather than a preprocessor macro like assert(). This means it fully supports C++ syntax and sees the template parameters correctly.

like image 114
Karl Nicoll Avatar answered Nov 14 '22 22:11

Karl Nicoll