Since boost is forbidden in a company I work for I need to implement its functionality in pure C++. I've looked into boost sources but they seem to be too complex to understand, at least for me. I know there is something called static_assert() in the C++0x standart, but I'd like not to use any C++0x features.
One other trick (which can be used in C) is to try to build an array with a negative size if the assert fail:
#define ASSERT(cond) int foo[(cond) ? 1 : -1]
as a bonus, you may use a typedef instead of an object, so that it is usable in more contexts and doesn't takes place when it succeed:
#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1]
finally, build a name with less chance of name clash (and reusable at least in different lines):
#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1]
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
int main() {
StaticAssert< (4>3) >(); //OK
StaticAssert< (2+2==5) >(); //ERROR
}
Here is my own implementation of static assertions extracted from my code base: Pre-C++11 Static Assertions Without Boost.
Usage:
STATIC_ASSERT(expression, message);
When the static assertion test fails, a compiler error message that somehow contains the STATIC_ASSERTION_FAILED_AT_LINE_xxx_message is generated.
message has to be a valid C++ identifier, like no_you_cant_have_a_pony which will produce a compiler error containing:
STATIC_ASSERTION_FAILED_AT_LINE_1337_no_you_cant_have_a_pony :)
#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2) arg1##arg2
/**
* Usage:
*
* <code>STATIC_ASSERT(expression, message)</code>
*
* When the static assertion test fails, a compiler error message that somehow
* contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated.
*
* /!\ message has to be a valid C++ identifier, that is to say it must not
* contain space characters, cannot start with a digit, etc.
*
* STATIC_ASSERT(true, this_message_will_never_be_displayed);
*/
#define STATIC_ASSERT(expression, message)\
struct CONCATENATE(__static_assertion_at_line_, __LINE__)\
{\
implementation::StaticAssertion<static_cast<bool>((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\
};\
typedef implementation::StaticAssertionTest<sizeof(CONCATENATE(__static_assertion_at_line_, __LINE__))> CONCATENATE(__static_assertion_test_at_line_, __LINE__)
// note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE
namespace implementation {
template <bool>
struct StaticAssertion;
template <>
struct StaticAssertion<true>
{
}; // StaticAssertion<true>
template<int i>
struct StaticAssertionTest
{
}; // StaticAssertionTest<int>
} // namespace implementation
STATIC_ASSERT(true, ok);
STATIC_ASSERT(false, ko);
int main()
{
return 0;
}
You could simply copy the macro from the Boost source file to your own code. If you don't need to support all the compilers Boost supports you can just pick the right definition for your compiler and omit the rest of the #ifdefs in that file.
I believe this should work:
template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true>{};
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>())
I am using the following header file, with code ripped from someone else...
#ifndef STATIC_ASSERT__H
#define STATIC_ASSERT__H
/* ripped from http://www.pixelbeat.org/programming/gcc/static_assert.html */
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
/* microsoft */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
/* This can't be used twice on the same line so ensure if using in headers
* that the headers are not included twice (by wrapping in #ifndef...#endif)
* Note it doesn't cause an issue when used on same line of separate modules
* compiled with gcc -combine -fwhole-program. */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif
/* http://msdn.microsoft.com/en-us/library/ms679289(VS.85).aspx */
#ifndef C_ASSERT
#define C_ASSERT(e) STATIC_ASSERT(e)
#endif
#endif
Related
I'm working on a wgl loader and typedef'd each openGL function that I use like this:
/*Let's say I'm defining n functions*/
typedef return_t (*f1)(params)
f1 _glFunc1;
#define glFunc1(params) _glFunc1(params)
...
typedef return_t (*fn)(params)
fn _glFuncn;
#define glFuncn(params) _glFuncn(params)
Then to get the definitions of these functions I have to use wglGetProcAddress or GetProcAddress and then cast the result to f1, f2 ...
I tried to automate the casting with this macro:
#define GetFuncDef(glFunc) _##glFunc = (f##(__LINE__ - startingLineNumber + 1))GetProcAddress(#glFunc)
Where startingLineNumber is the first line that I use this macro in(in my case it's 22),
but the preprocessor does not compute __LINE__ - startingLineNumber.
Is there some way to force it to do so?
EDIT:
startingLineNumber isn't a variable, macro etc. It's written out as a literal number in my code. like this:
#define GetFuncDef(glFunc) _##glFunc = (f##(__LINE__ - 22 + 1))GetProcAddress(#glFunc), where 22 would be startingLineNumber
Similar to C Preprocessor output int at Build first you have to implement operations:
typedef return_t (*f1)(params)
typedef return_t (*f2)(params)
void *GetProcAddress(charr *);
#define SUB_10_0 10
#define SUB_10_1 9
#define SUB_10_2 8
// etc. for each each possible combination, 1000 of lines ...
#define SUB_21_20 1
// etc. for each each possible combination, 1000 of lines ...
#define SUB_IN(a, b) SUB_##a##_##b
#define SUB(a, b) SUB_IN(a, b)
#define CONCAT_IN(a, b) a##b
#define CONCAT(a, b) CONCAT_IN(a, b)
#define startingLineNumber 20
#define GetFuncDef(glFunc) (CONCAT(f, SUB(__LINE__, startingLineNumber)))GetProcAddress(#glFunc)
int main() {
f1 a = GetFuncDef();
}
Then gcc -E outputs:
typedef return_t (*f1)(params)
typedef return_t (*f2)(params)
void *GetProcAddress(charr *);
int main() {
f1 a = (f1)GetProcAddress("");
}
In a similar fashion mentioned here Boost and P99 libraries can be used.
Is there a way to write a compile-time assertion that checks if some type has any padding in it?
For example:
struct This_Should_Succeed
{
int a;
int b;
int c;
};
struct This_Should_Fail
{
int a;
char b;
// because there are 3 bytes of padding here
int c;
};
Since C++17 you might be able to use std::has_unique_object_representations.
#include <type_traits>
static_assert(std::has_unique_object_representations_v<This_Should_Succeed>); // succeeds
static_assert(std::has_unique_object_representations_v<This_Should_Fail>); // fails
Although, this might not do exactly what you want it to do. Check the linked cppreference page for details.
Edit: Check Indiana's answer.
Is there a way to write a compile-time assertion that checks if some type has any padding in it?
Yes.
You can sum the sizeof of all members and compare it to the size of the class itself:
static_assert(sizeof(This_Should_Succeed) == sizeof(This_Should_Succeed::a)
+ sizeof(This_Should_Succeed::b)
+ sizeof(This_Should_Succeed::c));
static_assert(sizeof(This_Should_Fail) != sizeof(This_Should_Fail::a)
+ sizeof(This_Should_Fail::b)
+ sizeof(This_Should_Fail::c));
This unfortunately requires explicitly naming the members for the sum. An automatic solution requires (compile time) reflection. Unfortunately, C++ language has no such feature yet. Maybe in C++23 if we are lucky. For now, there are solutions based on wrapping the class definition in a macro.
A non-portable solution might be to use -Wpadded option provided by GCC, which promises to warn if structure contains any padding. This can be combined with #pragma GCC diagnostic push to only do it for chosen structures.
type I'm checking, the type is a template input.
A portable, but not fully satisfactory approach might be to use a custom trait that the user of the template can use to voluntarily promise that the type does not contain padding allowing you to take advantage of the knowledge.
The user would have to rely on explicit or pre-processor based assertion that their promise holds true.
To get the total field size without retyping each struct member you can use an X Macro
First define all the fields
#define LIST_OF_FIELDS_OF_This_Should_Fail \
X(int, a) \
X(char, b) \
X(int, c)
#define LIST_OF_FIELDS_OF_This_Should_Succeed \
X(long long, a) \
X(long long, b) \
X(int, c) \
X(int, d) \
X(int, e) \
X(int, f)
then declare the structs
struct This_Should_Fail {
#define X(type, name) type name;
LIST_OF_FIELDS_OF_This_Should_Fail
#undef X
};
struct This_Should_Succeed {
#define X(type, name) type name;
LIST_OF_FIELDS_OF_This_Should_Succeed
#undef X
};
and check
#define X(type, name) sizeof(This_Should_Fail::name) +
static_assert(sizeof(This_Should_Fail) == LIST_OF_FIELDS_OF_This_Should_Fail 0);
#undef X
#define X(type, name) sizeof(This_Should_Succeed::name) +
static_assert(sizeof(This_Should_Succeed) == LIST_OF_FIELDS_OF_This_Should_Succeed 0);
#undef X
or you can just reuse the same X macro to check
#define X(type, name) sizeof(a.name) +
{
This_Should_Fail a;
static_assert(sizeof(This_Should_Fail) == LIST_OF_FIELDS_OF_This_Should_Fail 0);
}
{
This_Should_Succeed a;
static_assert(sizeof(This_Should_Succeed) == LIST_OF_FIELDS_OF_This_Should_Succeed 0);
}
#undef X
See demo on compiler explorer
For more information about this you can read Real-world use of X-Macros
An alternate non-portable solution is to compare the size of the struct with a packed version with #pragma pack or __attribute__((packed)). #pragma pack is also supported by many other compilers like GCC or IBM XL
#ifdef _MSC_VER
#define PACKED_STRUCT(declaration) __pragma(pack(push, 1)) declaration __pragma(pack(pop))
#else
#define PACKED_STRUCT(declaration) declaration __attribute((packed))
#endif
#define THIS_SHOULD_FAIL(name) struct name \
{ \
int a; \
char b; \
int c; \
}
PACKED_STRUCT(THIS_SHOULD_FAIL(This_Should_Fail_Packed));
THIS_SHOULD_FAIL(This_Should_Fail);
static_assert(sizeof(This_Should_Fail_Packed) == sizeof(This_Should_Fail));
Demo on Compiler Explorer
See Force C++ structure to pack tightly. If you want to have an even more portable pack macro then try this
Related:
How to check the size of struct w/o padding?
Detect if struct has padding
In GCC and Clang there's a -Wpadded option for this purpose
-Wpadded
Warn if padding is included in a structure, either to align an element of the structure or to align the whole structure. Sometimes when this happens it is possible to rearrange the fields of the structure to reduce the padding and so make the structure smaller.
In case the struct is in a header that you can't modify then in some cases it can be worked around like this to get a packed copy of the struct
#include "header.h"
// remove include guard to include the header again
#undef HEADER_H
// Get the packed versions
#define This_Should_Fail This_Should_Fail_Packed
#define This_Should_Succeed This_Should_Succeed_Packed
// We're including the header again, so it's quite dangerous and
// we need to do everything to prevent duplicated identifiers:
// rename them, or define some macros to remove possible parts
#define someFunc someFunc_deleted
// many parts are wrapped in SOME_CONDITION so this way
// we're preventing them from being redeclared
#define SOME_CONDITION 0
#pragma pack(push, 1)
#include "header.h"
#pragma pack(pop)
#undef This_Should_Fail
#undef This_Should_Succeed
static_assert(sizeof(This_Should_Fail_Packed) == sizeof(This_Should_Fail));
static_assert(sizeof(This_Should_Succeed_Packed) == sizeof(This_Should_Succeed ));
This won't work for headers that use #pragma once or some structs that include structs in other headers though
As part of a Proof of Concept, I'm trying to trying to build code that I can use to build GLSL scripts. One of the first things I've done is create references to the GLSL types, and created a system where I can query, based on an enum (which is the type of the GLSL data type) the string-literal that represents it in GLSL code. Here's what it looks like:
#define VEC_EXPAND(name) g ## name ## 2, g ## name ## 3, g ## name ## 4
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)
enum class gtype : uint32_t {
gvoid,
gbool, gint, guint, gfloat, gdouble,
VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
MAT_EXPAND(mat), MAT_EXPAND(dmat),
gsampler2d
};
#undef VEC_EXPAND
#undef MAT_EXPAND
#define GLSL_EXPAND(name) #name
#define VEC_EXPAND(name) GLSL_EXPAND(name ## 2), GLSL_EXPAND(name ## 3), GLSL_EXPAND(name ## 4)
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)
template<class T, class... Tail, class Elem = typename std::decay<T>::type>
constexpr std::array<Elem, 1 + sizeof...(Tail)> make_array(T&& head, Tail&&... values)
{
return { std::forward<T>(head), std::forward<Tail>(values)... };
}
constexpr auto glsl_string_array = make_array(
"void", "bool", "int", "uint", "float", "double",
VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
MAT_EXPAND(mat), MAT_EXPAND(dmat),
"sampler2d"
);
constexpr const char * to_string_literal(gtype type) {
return glsl_string_array[uint32_t(type)];
}
std::string to_string(gtype type) {
return to_string_literal(type);
}
#undef GLSL_EXPAND
#undef VEC_EXPAND
#undef MAT_EXPAND
So far, I've had no problems with the functionality of the code, but that duplication of the code where I define the types as an enum, and then write them again as a string literal is definitely troubling to me. I'm going to have to add more types as well (these are hardly the only GLSL types!) and I would like to write similar code for writing OpenCL Kernel code (which will depend on similar semantics), so how can I reduce this code down so that I only need one declaration of each type?
Also, any advice which would reduce or even eliminate my use of Macros would be appreciated.
I don't know whether this fits your case, but I can suggest something like:
// things.inc
#ifndef GTYPE_VOID
#define GTYPE_VOID GTYPE_DECL(gvoid)
#endif
GTYPE_VOID
#undef GTYPE_VOID
#ifndef GTYPE_INT
#define GTYPE_INT GTYPE_DECL(gint)
#endif
GTYPE_INT
#undef GTYPE_INT
#ifndef GTYPE_FLOAT
#define GTYPE_FLOAT GTYPE_DECL(gfloat)
#endif
GTYPE_FLOAT
#undef GTYPE_FLOAT
You can then define the macro in the way you like, and include it in places where you need:
// things.cpp
enum class gtypes {
#define GTYPE_DECL(Thing) Thing,
#include "things.inc"
#undef GTYPE_DECL
};
const char *as_string(gtype t) {
switch (t) {
#define GTYPE_DECL(Thing) case gtype::Thing: return #Thing;
#include "things.inc"
#undef GTYPE_DECL
}
// or unreachable
return "(unknown)";
}
Also, you can try to use a constexpr map.
I'm looking to make a variadic macro that simply calls a certain function for every argument (say, up to 6). So far I've been using the following code in MSVC:
#define do_write2(x,y) do{do_write(x);do_write(y);}while(0)
#define do_write3(x,y,z) do{do_write(x);do_write(y);do_write(z);}while(0)
#define do_write4(x,y,z,w) do{do_write(x);do_write(y);do_write(z);do_write(w);}while(0)
#define do_write5(x,y,z,w,t) do{do_write(x);do_write(y);do_write(z);do_write(w);do_write(t);}while(0)
#define do_write6(x,y,z,w,t,u) do{do_write(x);do_write(y);do_write(z);do_write(w);do_write(t);do_write(u);}while(0)
#define expand(x) x
#define _get_write(_1,_2,_3,_4,_5,_6,name,...) name
#define dumpval(...) expand(_get_write(__VA_ARGS__,do_write6,do_write5,do_write4,do_write3,do_write2,do_write))expand((__VA_ARGS__))
The expand is needed due to a peculiar handling of __VA_ARGS__ in MSVC, otherwise I get
error C2660: 'do_write' : function does not take 6 arguments
However, now I need to build the same code in GCC, and its having trouble with it:
error: ‘do_write3’ was not declared in this scope
Simply removing the expand wrapper does the trick. However, is there any "correct" way to make the code compile in both cases without using #ifdef?
There are various techniques for variable-argument macros, discussed here: Variadic recursive preprocessor macros - is it possible?
Here are a few implementations that you might be interested in. Personally, I think call_vla2 is the best assuming you have C++11 support. If this is not possible, tell us more about your problem.
#include <iostream>
// target function
void z(int i) {
std::cout << "[" << i << "]\n";
}
// 1. manually specifying the argument count
#define call1(a) do{z(a);}while(0)
#define call2(a,b) do{z(a);z(b);}while(0)
#define call3(a,b,c) do{z(a);z(b);z(c);}while(0)
#define call_n(n, ...) call ## n (__VA_ARGS__)
// 2. using a variable-length array (GCC compatible)
// thanks to https://stackoverflow.com/a/824769/6096046
#define call_vla(...) do { \
int args[] = { __VA_ARGS__ }; \
for(size_t i = 0; i < sizeof(args)/sizeof(*args); i ++) \
z(args[i]); \
} while(0)
// 3. using a variable-length array and C++11
#define call_vla2(...) for(auto x : { __VA_ARGS__ }) z(x);
// 4. using C++11 variadic templates
template <typename... T>
void call_n_times() {}
template <typename... T>
void call_n_times(int a, T... other) {
z(a), call_n_times(other...);
}
#define call_template(...) call_n_times(__VA_ARGS__)
// tests
int main() {
call_n(1, 88); call_n(3, 1,2,3);
call_vla(88); call_vla(1,2,3);
call_vla2(88); call_vla2(1,2,3);
call_template(88); call_template(1,2,3);
return 0;
}
Is it possible to disable chunks of code with c/c++ preprocessor depending on some definition, without instrumenting code with #ifdef #endif?
// if ENABLE_TEST_SONAR is not defined, test code will be eliminated by preprocessor
TEST_BEGIN(SONAR)
uint8_t sonar_range = get_sonar_measurement(i);
TEST_ASSERT(sonar_range < 300)
TEST_ASSERT(sonar_range > 100)
TEST_END
Functionally equivalent to something as follows:
#ifdef TEST_SONAR
serial_print("test_case sonar:\r\n");
uint8_t sonar_range = get_sonar_measurement(i);
serial_print(" test sonar_range < 300:%d\r\n", sonar_range < 300);
serial_print(" test sonar_range > 100:%d\r\n", sonar_range > 100);
#endif TEST_SONAR
Multiple lines can be disabled only with #ifdef or #if but single lines can be disabled with a macro. Note that multiple lines can be combined with \
#ifdef DOIT
#define MYMACRO(x) \
some code \
more code \
even more \
#else
#define MYMACRO(x)
#endif
Then when you call MYMACRO anplace that code will either be included or not based on whether DOIT is defined
That's the closest you can come and is used frequently for debugging code
EDIT: On a whim I tried the following and it seems to work (in MSVC++ and g++):
#define DOIT
#ifdef DOIT
#define MYMACRO(x) x
#else
#define MYMACRO(x)
#endif
void foo(int, int, int)
{
}
int main(int, char **)
{
int x = 7;
MYMACRO(
if (x)
return 27;
for (int i = 0; i < 10; ++i)
foo(1, 2, 3);
)
}
No, the only way to disable sections of codes effectively using preprocessing is by #ifdef #endif. Theoretically, you could use #if identifier, but it's better to stick to checking whether a variable is defined.
Another option (perhaps) is to use a preprocessing macro:
Edit:
Perhaps using plain functions and #ifdef might work better?
function test_function() {
/* Do whatever test */
}
#define TESTING_IDENTIFIER
#define TEST( i, f ) if ((i)) do { f } while (0)
Then, for each test, you define a unique identifier and call it by providing the identifier first and the function (with parenthesis) second.
TEST( TESTING_IDENTIFIER, test_function() );
Finally, f can be anything that's syntactically correct -- You don't have to create a function for every test, you can put the code inline.
I will anyway mention an obvious solution of
#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
...
TEST_SONAR
code
TEST_SONAR_END
The code will still get compiled, not completely removed, but some smart compilers might optimize it out.
UPD: just tested and
#include <iostream>
using namespace std;
//#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
int main() {
TEST_SONAR
cout << "abc" << endl;
TEST_SONAR_END
}
produces absolutely identical binaries with cout line commented out and non commented, so indeed the code is stripped. Using g++ 4.9.2 with -O2.