开发者

C++ macro and templates

开发者 https://www.devze.com 2022-12-20 20:24 出处:网络
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

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>);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号