2010-02-19 61 views
4

有没有办法通过C++宏和模板

std::map<std::string, float> 

作为参数传递给宏?

(问题是, “” 用于由宏分裂

std::map<std::string 

float> 

作为独立参数。我想避免这种情况。

+0

我认为他们听说你第一次...... – 2010-02-19 08:38:23

+0

难道这就是为C?还是C++? – AnT 2010-02-19 08:39:43

+3

只是好奇,我们可以看到有问题的宏吗?可能有更好的方法来完成你使用它的任何任务。 – 2010-02-19 08:43:16

回答

2

一个不起眼的解决方法是“隐藏”另一个宏内的逗号

#define ARGUMENT std::map<std::string, float> 
YOUR_MACRO(ARGUMENT) 
#undef ARGUMENT 

但是,如果YOUR_MACRO本身需要将其另一个级别传播到另一个宏,它将遇到同样的问题。

+0

'typedef'克服了嵌套宏问题,但更具永久性。 – 2010-02-19 08:42:42

+0

我第二种'typedef'方法。每当有一个替代品不涉及一个宏并提供相同的易用性......你最好没有一个宏。 – 2010-02-19 09:32:06

+0

哦,真是太酷了。如果可以的话,我会给你+10。谢谢! – 2013-02-08 07:40:37

6

不,没有办法做到这一点,缺少使用typedef。例如,BOOST_FOREACH遭受同样的问题。

+0

+1使用typedef – James 2010-02-19 09:32:21

+0

有几种方法,如果你需要进行一些预处理编程。尽管这可能会给用户带来一些负担,这取决于你所追求的内容,并且需要对宏进行量身定制来处理它......查看我的答案。 – 2010-02-19 09:33:42

6

尝试使用模板而不是宏。

斯科特迈尔斯:C++有效 项目2:不想consts,枚举和内联到#define语句

+1

'项目2'在这里不适用:它没有提到模板,只是常量......虽然我同意一般的观点,但如果它总是可能的话......那将会很棒。 – 2010-02-19 09:14:54

+1

它是第2项的内联。我在这里提到模板,因为宏不关心类型,这就是为什么你通常不能用普通函数替换它们。但是使用模板可以让你做到这一点。我认为迈尔使用最小/最大宏对模板进行演示。 – Totonga 2010-02-19 09:55:24

0

我有类似的东西在几个月前,如果你使用宏的,并有包含参数的逗号(“” ),你需要包裹于额外parenthasis即:

#define DEF(ret,conv,name,args) typedef ret (conv * name)(args) 

//usage 
DEF(void,__cdecl,Foo,(int a1, string a2)); 

这种方法可能与某些东西冲突/在某些情况下无效的,这样的例子(它导致它成为一个无效的C样式转换):

#define MY_VAR(type,name) type name 

//usage 
MY_VAR((std::map<std::string, float>),Map); 

虽然有一种解决此问题的方法,但它需要您的编译器支持可变宏(GCC | MSVC):

#define _W(...) __VA_ARGS__ 
#define VAR(x,y) x y 

VAR(_W(std::map<std::string, float>),Map); 
+0

不要在宏定义中加上'args',它带括号。 – 2010-02-19 09:30:53

+0

如果有人使用singluar参数,使用宏时可以省略父外部,这就是为什么args是parenthasized,剩下的时间什么都不做,超过的paranthasis被删除/忽略 – Necrolis 2010-02-19 12:30:58

+1

括号似乎不是忽略。第一个示例展开为'(std :: map )Map;',它根本不编译(在未声明的标识符Map上是C风格的转换)。 – UncleBens 2010-02-19 17:20:23

5

是的,有一种方法,它是间接的。

正如你所说,一个宏在其解释中相当愚蠢。但它仍然认可括号。

实施例:BOOST_MPL_ASSERT((boost::is_same<int,int>))

它通过使用括号的另一电平,由此形成Tuple(从宏观角度)。

如果您使用Boost.Preprocessor库,您可以轻松地“解开”Tuple以免其内容受到损害。不幸的是,你应该知道前期一个元组的大小,所以你需要一个额外的参数

#define MY_MACRO(Size, TemplatedType, Name)\ 
    BOOST_PP_TUPLE_REM(Size)(TemplatedType) Name 

而且在行动:

MY_MACRO(2, (std::map<int,std::string>), idToName); 
    // expands to 'std::map<int,std::string> idToName' 
idToName[1] = "Smith"; 

所以,是的,它是可能的,但宏必须是明确定制来处理它。

+0

我还应该补充一点,它可能很麻烦,因为用户需要计算',':/ – 2010-02-19 09:36:29

0

是的,只要您能安排它,std::map<std::string, float>就是您的最终参数或唯一参数。只需使用__VA_ARGS__,例如:

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