C++ macro and templates
Is there a way to pass
std::map<std::string, float>
as an argument to a macro?
(the problem is that the "," is used by the ma开发者_开发百科cro to split
std::map<std::string
and
float>
as separate arguments. I would like to avoid this.
No, there isn't a way to do this, short of using a typedef. BOOST_FOREACH, for example, suffers the same problem.
Try to use a template instead of the macro.
Scott Meyers : Effective C++ Item 2: Prefer consts, enums, and inlines to #defines
Yes there is a way, it's indirect though.
As you have said, a macro is rather dumb in its interpretation. However it still recognize parenthesis.
Example: BOOST_MPL_ASSERT((boost::is_same<int,int>))
It works by using another level of parenthesis, thus forming a Tuple
(from the macro point of view).
If you use the Boost.Preprocessor library, you can easily "unwrap" a Tuple
to get its content unscathed. Unfortunately you are supposed to know the size of a tuple upfront, so you need an additional parameter
#define MY_MACRO(Size, TemplatedType, Name)\
BOOST_PP_TUPLE_REM(Size)(TemplatedType) Name
And in action:
MY_MACRO(2, (std::map<int,std::string>), idToName);
// expands to 'std::map<int,std::string> idToName'
idToName[1] = "Smith";
So, yes it is possible, but the macro has to be explicitly tailored to handle it.
One inelegant workaround is to "hide" the comma inside another macro
#define ARGUMENT std::map<std::string, float>
YOUR_MACRO(ARGUMENT)
#undef ARGUMENT
However, if YOUR_MACRO
itself needs to propagate it another level down into another macro, it will run into the same problem.
I had something similar a few months back, if your using macro's and have parameters that contain comma's (','), you need to encase them in extra parenthasis ie:
#define DEF(ret,conv,name,args) typedef ret (conv * name)(args)
//usage
DEF(void,__cdecl,Foo,(int a1, string a2));
this method might conflict with certain things/be invalid in certain cases, like this example(it cause it to become an invalid c-style cast):
#define MY_VAR(type,name) type name
//usage
MY_VAR((std::map<std::string, float>),Map);
there is one way to address this problem though, but it requires your compiler to support variadic macros(GCC|MSVC):
#define _W(...) __VA_ARGS__
#define VAR(x,y) x y
VAR(_W(std::map<std::string, float>),Map);
Yes, so long you can arrange it so that std::map<std::string, float>
is your final or only parameter. Just use __VA_ARGS__
, for example:
#define MAKE_A_NEW_ONE_OF_THESE(a, ...) __VA_ARGS__ *a = new __VA_ARGS__
MAKE_A_NEW_ONE_OF_THESE(pMyMap, std::map<std::string, float>);
精彩评论