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.
Related
is there a way/trick to make a #define directive evaluate some condition?
for example
#define COM_TIME_DO(COND, BODY) \
#if (COND) BODY
#else
#endif
it's ok also to use template but body must be an arbitrary (correct in the context is used to) piece of code, simply just present or not in the source depending of COND.
as it is now the previous code doesn't even compile.
the goal of this question is primarly a better knowledge of the language and what i'm trying to do is define a debug macro system that i can activate selectively on certain parts of code for example:
A.hpp
#define A_TEST_1 1
#define A_TEST_2 0
Class A {
...
COM_TIME_DO(A_TEST_1,
void test_method_1();
)
COM_TIME_DO(A_TEST_2,
void test_method_2();
)
};
A.cpp
COM_TIME_DO(A_TEST_1,
void A::test_method_1() {
...
})
COM_TIME_DO(A_TEST_2,
void A::test_method_2() {
...
})
i was just asking if it was POSSIBLE because i like it more than the #if ... #endif.
If the expression of the condition will always expand to 1 or 0 (or some other known set of values) it is possible to implement such a macro.
#define VALUE_0(...)
#define VALUE_1(...) __VA_ARGS__
#define COM_TIME_DO_IN(A, ...) VALUE_##A(__VA_ARGS__)
#define COM_TIME_DO(A, ...) COM_TIME_DO_IN(A, __VA_ARGS__)
However, do not use such code in real life. Use #if and write clear, readable and maintainable code that is easy to understand for anyone.
is there a way/trick to make a #define directive evaluate some condition?
This depends on what the condition actually is.
Since you mentioned #if I'm assuming you'd like to evaluate an integer constant expressions.
Doing this in a macro single macro isn't possible, without implementation defined _Pragmas, but you can do it with an include + a macro definition:
#define COM_TIME_DO ((1 > 2), true, false)
#include "com-time-do.h"
// ^-- generates: false
#define COM_TIME_DO ((1 == 1), true_func();, false_func();)
#include "com-time-do.h"
// ^-- generates: true_func();
where com-time-do.h is defined as follows:
// com-time-do.h
#define SCAN(...) __VA_ARGS__
#define SLOT_AT_COND(a,b,c) a
#define SLOT_AT_THEN(a,b,c) b
#define SLOT_AT_ELSE(a,b,c) c
#if SCAN(SLOT_AT_COND COM_TIME_DO)
SCAN(SLOT_AT_THEN COM_TIME_DO)
#else
SCAN(SLOT_AT_ELSE COM_TIME_DO)
#endif
#undef COM_TIME_DO
Although, as KamilCuk said, please write reasonable code and don't use this.
I want to use macros to quickly create inlined functions in headers, these functions are related to a base class which I am subclassing. I'll put the definitions inside the base class header but I do not want to pollute everything that include these headers with all macro definitions, so I would like to write something like this (which unfortunately doesn't work):
#define BEGIN_MACROS \
#define MACRO_1(...) ...\
#define MACRO_2(...) ...\
#define MACRO_3(...) ...
#define END_MACROS \
#undef MACRO_1\
#undef MACRO_2\
#undef MACRO_3
And then use it like:
BEGIN_MACROS
MACRO_1(...)
MACRO_2(...)
MACRO_3(...)
END_MACROS
perhaps should I use something like this?
#include "definemacros.h"
MACRO_1(...)
MACRO_2(...)
MACRO_3(...)
#include "undefmacros.h"
And put definitions and "undefinitions" in two separate headers...
Or is there a better approach overall to overcome this kind of problems?
Or do you suggest to avoid at all the use of macros and/or macros in headers?
Edited to include specific use case:
definition:
#define GET_SET_FIELD_VALUE_INT(camelcased, underscored)\
inline int rget ## camelcased () { return this->getFieldValue( #underscored ).toInt(); }\
inline void rset ## camelcased (int value) { this->setFieldValue( #underscored , value); }
use:
class PaymentRecord : public RecObj
{
public:
GET_SET_FIELD_VALUE_INT(PriceIndex, price_index)
//produces this
inline int rgetPriceIndex() { return this->getFieldValue("price_index").toInt(); }
inline void rsetPriceIndex(int value) { this->setFieldValue("price_index", value); }
};
you can not stack up more defines into single line (at least to my knowledge... What I would try to do is encapsulate those into 2 separate files instead like this:
file macro_beg.h:
#define MACRO_1(...) ...
#define MACRO_2(...) ...
#define MACRO_3(...) ...
file macro_end.h:
#undef MACRO_1
#undef MACRO_2
#undef MACRO_3
It just like your second case but the macros are not in single line ...
#include "macro_beg.h"
MACRO_1(...);
MACRO_2(...);
MACRO_3(...);
#include "macro_end.h"
But as Some programmer dude commented this might not work properly or at all depending on the compiler preprocessor and macro complexity or nesting with class/template code. For simple stuff however this should work.
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;
}
I would like to run macros on a list of class names to avoid copy/pasting errors and hassle.
Imagine, as a simple example, that every class in my SDK needs to call a static allocation method before it is used. So, every time I add a new class, I have to manually add the following line at initialization:
MyNewClass::allocate();
And I also need to do the same for initialization and destruction.
So, instead of doing this manually every time, I was wondering if there was a way to write a list of all my class names somewhere, then define a macro to call the corresponding methods for each class in the list. Something in the lines of:
#define ALLOCATE( TheClass ) TheClass ## ::allocate();
But instead of just passing TheClass as an argument, I'd like to pass a list of my classes. So by calling:
ALLOCATE_ALL( ClassA, ClassB, ClassC )
it would expand to:
ClassA::allocate();
ClassB::allocate();
ClassC::allocate();
Ultimately, I would like to be able to define a class list and have multiple macros iterate over it. Something in the lines of:
ALLOCATE_ALL( MyClassList )
INIT_ALL( MyClassList )
DESTROY_ALL( MyClassList )
I've already taken a look at variadic macros but, if I understand the concept correctly, you have to define as many macros as the final number of arguments; and that is simply not viable in my case.
Is this possible at all?
Thanks for any help and/or feedback.
If you are satisfied with having one list of classes, you can use the following trick:
#define MY_CLASSES X(ClassA) X(ClassB) X(ClassC)
Then you can do something like:
#define X(a) a::allocate();
MY_CLASSES
#undef X
To do something else, you can do:
#define X(a) a::init();
MY_CLASSES
#undef X
You could use a variadic function template :
#include <iostream>
// Thanks to Jarod42 for improving it !
template <class... TClasses>
void allocateAll() {
std::initializer_list<int>{(TClasses::allocate(), void(), 0)...};
}
struct C1 { static void allocate() { std::cout << "allocated C1\n"; } };
struct C2 { static void allocate() { std::cout << "allocated C2\n"; } };
struct C3 { static void allocate() { std::cout << "allocated C3\n"; } };
int main()
{
allocateAll<C1, C2, C3>();
return 0;
}
Outputs :
allocated C1
allocated C2
allocated C3
The functions are called in the same order that you pass their classes in.
You can also centralize the classes list :
// Use a template instead of a function so you can typedef it
template <class... TClasses>
struct ClassesList {
static void allocateAll() {
std::initializer_list<int>{(TClasses::allocate(), void(), 0)...};
}
// Add any other utilities here
private:
ClassesList();
};
// Declare your list
using MyClassesList = ClassesList<C1, C2, C3>;
int main(int, char**) {
// Just as before
MyClassesList::allocateAll();
}
To improve slightly the answer given by LindyLancer suggesting X-macros you could have a seperate file
// file my_classes.def
#ifndef MY_CLASS
#error MY_CLASS should be defined before including my_classes.def
MY_CLASS(ClassA)
MY_CLASS(ClassB)
/// etc...
#undef MY_CLASS
Then you would include that several times, e.g.
#define MY_CLASS(Classname) class Classname;
#include "my_classes.def"
and later, inside some initializer (or your main)
#define MY_CLASS(Classname) Classname::init();
#include "my_classes.def"
Using Boost.Preprocessor :
#include <boost/preprocessor/seq/for_each.hpp>
#define MyClassList \
(ClassA) \
(ClassB) \
(ClassC)
#define ALLOCATE_ALL( R, DATA, ELEM ) \
ELEM :: allocate();
#define INIT_ALL( R, DATA, ELEM ) \
ELEM :: init();
//...
BOOST_PP_SEQ_FOR_EACH( ALLOCATE_ALL, _, MyClassList )
BOOST_PP_SEQ_FOR_EACH( INIT_ALL, _, MyClassList )
You can define a generic macro that iterates, but the one time definition of it is ugly. This is because you do need one macro definition for each argument, up to the max number of nesting levels supported by your compiler (I believe the minimum is at least 63, but GCC is only limited by available memory). But since it is generic, you may find other uses of it.
For up to 5, a possible implementation is:
#define M_ITER(M, ...) \
M_ITER_(__VA_ARGS__, _5, _4, _3, _2, _1)(M, __VA_ARGS__)
#define M_ITER_(_1, _2, _3, _4, _5, X, ...) M_ITER ## X
#define M_ITER_1(M, X) M(X)
#define M_ITER_2(M, X, ...) M(X) M_ITER_1(M, __VA_ARGS__)
#define M_ITER_3(M, X, ...) M(X) M_ITER_2(M, __VA_ARGS__)
#define M_ITER_4(M, X, ...) M(X) M_ITER_3(M, __VA_ARGS__)
#define M_ITER_5(M, X, ...) M(X) M_ITER_4(M, __VA_ARGS__)
This is basically how BOOST_PP_SEQ_FOR_EACH is implemented.
And then, you could use it for your purpose like this:
#define ALLOCATE_ALL(...) M_ITER(ALLOCATE, __VA_ARGS__)
#define INIT_ALL(...) M_ITER(INIT, __VA_ARGS__)
#define DESTROY_ALL(...) M_ITER(DESTROY, __VA_ARGS__)
ALLOCATE_ALL(ClassA, ClassB, ClassC)
INIT_ALL(ClassA, ClassB, ClassC)
DESTROY_ALL(ClassA, ClassB, ClassC)
The accepted answer by Lindydancer is unsatisfactory to me because it relies on repeatedly redefining the X macro, which seems mysterious on use and could lead to collisions.
Instead, I prefer a variation that accepts the name of the macro as a parameter:
#define FOR_EACH_CLASS(macro) \
macro(ClassA) \
macro(ClassB) \
macro(ClassC)
This would be used liked like:
#define CALL_ALLOCATE(classname) classname::allocate();
FOR_EACH_CLASS(CALL_ALLOCATE)
#undef CALL_ALLOCATE /* optional undef */
There is another answer to a related question: Real-world use of X-Macros that gives more examples of the technique. (Note that, in that question, the accepted answer once again relies on redefining a macro with a particular name, whereas the one I linked accepts the macro name as a parameter.)
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