Concat Macro argument with namespace - c++

I have a macro, where one of the arguments is an enum value, which is given without specifying the namespace scope. However somewhere inside the macro I need to access it (obviously I must define the namespace there), but I can't seem to concat the namespace name with the template parameter. Given the following samplecode the compiler complains that pasting :: and Val doesnt give a valid preprocessor token (it works fine for concating get and a to getVal though).
namespace TN
{
enum Info
{
Val = 0
};
}
#define TEST(a) TN::Info get ## a(){return TN::##a;}
TEST(Val)
So is there any way to make this work without using another argument and basically specifying the value to be used twice (e.g. #define TEST(a,b) TN::Info get ## a(){return b;})?

## is a token pasting operator, i.e. it should make a single token out of multiple bits of token and as the compiler says, ::Val isn't a single token, it's two tokens.
Why do you need think you need the second ## at all? What's wrong with this.
#define TEST(a) TN::Info get ## a () { return TN::a; }

Only use ## when you want to concatenate two items and have the compiler treat the result as a single token (e.g. an identifier).
In your macro, the first use of ## is correct, as you are trying to construct an identifier by pasting together get and the contents of a, but second use of ## is spurious, as you just want to make an identifier out of the contents of a and the :: operator is a separate entity to that. GCC will complain about this (though MSVC++ copes).
#define TEST(a) TN::Info get ## a(){return TN::a;}
should work.

Related

Getting a string of class variable via macro?

I have the following method for various test cases:
test_case(mystruct->myvar1, "myvar1", ...);
test_case(mystruct->myvar2, "myvar2", ...);
test_case(mystruct->myvar3, "myvar3", ...);
Is there a way i can avoid having to type myvar1 twice, once as the variable and once as a string. ?
Sure there is.
The question is is that a good idea?
#define MY_TEST(object, value, ...) do { test_case(object->value, #value , __VARARGS__); } while(false)
Code:
MY_TEST(mystruct, myvar1, ...);
MY_TEST(mystruct, myvar2, ...);
MY_TEST(mystruct, myvar3, ...);
Excplanation:
In the macro:
#define MY_TEST(object, value, ...)
The words: object and value become parameters to the macro. And are replaced identically in the expression on the right. If a parameter is prefixed with # then it is stringified by adding double quotes around it.
object->value, #value => object->value, "value"
Macros can also have a variable argument list represented by the ... which is replaced by using __VARARGS__ on the destination side. There is one limitation with using varargs in that it must match at least one parameter (i.e it can not match zero parameters (they may have fixed that but not sure)).
The reason to add the do { ... } while(false) is me being pedantic when using macros to make sure that the expression is treated like a statement. The compiler will optimize this away so there is no extra code and the statement is executed exactly once. I find it good practice to be overly careful and pedantic when using macros as there is little protection from the pre-processor (and the language has tried to evolve away from using macros in the first place).
You can use stringify:
#define F(a) a, #a
F(x) // x, "x"

C++ preprocessor token pasting for namespace qualification

I am having trouble with the preprocessor token pasting operator in gcc 4.7.1 (std=c++11). Namely, consider the following code:
// Create a name for a global map (this works)
#define GLOBAL_MAP(name) g_map_ ## name // This works fine
// Now, namespace qualify this map (this fails to compile when used)
#define NS_QUAL_GLOBAL_MAP(name) SomeNamespace:: ## GLOBAL_MAP(name)
Usage scenarios - first the map definitions:
std::map<std::string,std::string> GLOBAL_MAP(my_map);
namespace SomeNamespace
{
std::map<std::string,std::string> GLOBAL_MAP(my_map);
}
Now the usage:
void foo()
{
bar(GLOBAL_MAP(my_map)); // This compiles fine
baz(NS_QUAL_GLOBAL_MAP(my_map)); // This fails to compile with:
// error: pasting "::" and "NAME_MAP" does not give a
// valid preprocessing token
}
What I believe might be happening is that it is interpreting GLOBAL_MAP after ## as a token for pasting rather than a macro to be further expanded. How do I get around this?
Token pasting generates a single token for the compiler to read. This isn’t what you want here — :: is a valid C++ token on its own, but ::g_map_my_map isn’t a token that the compiler knows.
Hence, remove the token pasting operator:
#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)
You don't need the ## operator after ::. The ## operator is used to form a single token, but SomeNamespace::g_map_mymap are multiple tokens anyway. Just do
#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)
You just want SomeNamespace:: GLOBAL_MAP(name).
You can't join a name like g_map_my_map to the :: token, because ::g_map_my_map is not a valid token, it's two tokens. So just put them next to each other, don't try to join them.

A previously defined constant, given as macro argument, is considered as string literal

Let's say I have defined a macro which does this
#define MY_MACRO(NAME) \
std::string get##NAME() const \
{ \
return doSomething(#NAME); \
}
Where doSomething method signature will be something like this
std::string doSomething(const std::string& parameter);
This works pretty well when the NAME macro parameter has no dashes in it.
For example :
#define MY_MACRO(thisIsA_test) // Works
But, when I have a dash in my string (this can happen) it won't work because dashes are not allowed in method names
#define MY_MACRO(thisIsA-test) // does NOT WORK
I have tried to work it around this way
#define thisIsAtest "thisIsA-test"
#define MY_MACRO(thisIsAtest)
Everything compiles just fine and I have the getthisIsAtest method generated but unfortunately the macro is not resolved and "thisIsAtest" is kept as string literal.
In other words the doSomething parameter string value will be "thisIsAtest" whereas I was expecting "thisIsA-test".
To expand the macro argument, just use an indirection macro.
#define stringize_literal( x ) # x
#define stringize_expanded( x ) stringize_literal( x )
Your use-case:
return doSomething( stringize_expanded( NAME ) );
Now the method will be named with name of the macro, and the function will be called with the contents of the macro. Somewhat questionable in terms of organization, but there you have it.
Why it works:
By default, macro arguments are expanded before being substituted. So if you pass thisIsAtest to parameter NAME, the macro expansion will replace NAME with "thisIsA-test". The pre-expansion step does not apply when you use a preprocessor operator # or ## though.
In your original code, one use of NAME is subject to ## and the other is subject to # so the macro definition of thisIsAtest never gets used. I just introduced a macro stringize_expanded which introduces an artificial use of NAME (via x) which is not subject to an operator.
This is the idiomatic way to use # and ##, since the expansion is desired more often than the literal macro name. You do happen to want the default behavior for ## in this case, but it could be considered a case of poor encapsulation (as the name of an interface is used to produce output), if you wanted to apply real programming principles to the problem.
There's nothing to work around.
As you have said yourself, dashes are not valid in function names.
So, do not use them.

C++ Preprocessor metaprogramming: obtaining an unique value?

I'm exploiting the behavior of the constructors of C++ global variables to run code at startup in a simple manner. It's a very easy concept but a little difficult to explain so let me just paste the code:
struct _LuaVariableRegistration
{
template<class T>
_LuaVariableRegistration(const char* lua_name, const T& c_name) {
/* ... This code will be ran at startup; it temporarily saves lua_name and c_name in a std::map and when Lua is loaded it will register all temporarily global variables in Lua. */
}
};
However manually instantiating that super ugly class every time one wants to register a Lua global variable is cumbersome; that's why I created the following macro:
#define LUA_GLOBAL(lua_name, c_name) static Snow::_LuaVariableRegistration _____LuaGlobal ## c_name (lua_name, c_name);
So all you have to do is put that in the global scope of a cpp file and everything works perfectly:
LUA_GLOBAL("LuaIsCool", true);
There you go! Now in Lua LuaIsCool will be a variable initialized to true!
But, here is the problem:
LUA_GLOBAL("ACCESS_NONE", Access::None);
Which becomes:
static Snow::_LuaVariableRegistration _____LuaGlobalAccess::None ("ACCESS_NONE", &Access::None);
:((
I need to concatenate c_name in the macro or it will complain about two variables with the same name; I tried replacing it with __LINE__ but it actually becomes _____LuaGlobalAccess__LINE__ (ie it doesn't get replaced).
So, is there a way to somehow obtain an unique string, or any other workaround?
PS: Yes I know names that begin with _ are reserved; I use them anyway for purposes like this being careful to pick names that the standard library is extremely unlikely to ever use. Additionally they are in a namespace.
You need to add an extra layer of macros to make the preprocessor do the right thing:
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define LUA_GLOBAL(lua_name, c_name) ... TOKENPASTE2(_luaGlobal, __LINE__) ...
Some compilers also support the __COUNTER__ macro, which expands to a new, unique integer every time it is evaluated, so you can use that in place of __LINE__ to generate unique identifiers. I'm not sure if it's valid ISO C, although gcc accepts its use with the -ansi -pedantic options.

Macro expansion in C++

How can I define a macro (or a workaround for this) where the parameter is at the beginning of the line?
#define SINGLETON_IMPLEMENTATION(className) \
##className* ##className::instance_ = NULL;
This give a compiler warning (GCC 3.2.3): " '##' cannot appear at either end of a macro expansion"
You only need ## to append a parameter to another string. Your macro can be recast as
#define SINGLETON_IMPLEMENTATION(className) \
className* className::instance_ = NULL;
## is the concatenation operator; the compiler is just complaining about that.
You cannot concatenate a token without something before it, i.e. at the beginning of the macro expansion; just try to remove the ## at the beginning of the second line.
Also the second ## seems wrong. If you just want to initialize a singleton pointer, remove both ##s from your macro.