PoP*_*PoP 93 c c++ macros c-preprocessor
假设我们有这样的宏
#define FOO(type,name) type name
Run Code Online (Sandbox Code Playgroud)
我们可以使用哪个
FOO(int, int_var);
Run Code Online (Sandbox Code Playgroud)
但并不总是那么简单:
FOO(std::map<int, int>, map_var); // error: macro "FOO" passed 3 arguments, but takes just 2
Run Code Online (Sandbox Code Playgroud)
我们当然可以这样做:
typedef std::map<int, int> map_int_int_t;
FOO(map_int_int_t, map_var); // OK
Run Code Online (Sandbox Code Playgroud)
这不是非常符合人体工程学的.必须处理类型不兼容的问题.知道如何用宏来解决这个问题吗?
not*_*ser 108
如果你不能使用括号而你不喜欢Mike的SINGLE_ARG解决方案,那么只需定义一个COMMA:
#define COMMA ,
FOO(std::map<int COMMA int>, map_var);
Run Code Online (Sandbox Code Playgroud)
如果您想要对某些宏参数进行字符串化,这也会有所帮助,如
#include <cstdio>
#include <map>
#include <typeinfo>
#define STRV(...) #__VA_ARGS__
#define COMMA ,
#define FOO(type, bar) bar(STRV(type) \
" has typeid name \"%s\"", typeid(type).name())
int main()
{
FOO(std::map<int COMMA int>, std::printf);
}
Run Code Online (Sandbox Code Playgroud)
打印std::map<int , int> has typeid name "St3mapIiiSt4lessIiESaISt4pairIKiiEEE".
eca*_*mur 100
因为尖括号也可以代表(或发生在)比较运算符<,>,<=和>=,宏扩展不能像它括号内确实忽略角括号内的逗号.(对于方括号和大括号,这也是一个问题,即使它们通常作为平衡对出现.)您可以将宏参数括在括号中:
FOO((std::map<int, int>), map_var);
Run Code Online (Sandbox Code Playgroud)
问题是该参数在宏扩展中保持括号,这可以防止在大多数上下文中将其作为类型读取.
解决此问题的一个很好的技巧是在C++中,您可以使用函数类型从带括号的类型名称中提取类型名称:
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
FOO((std::map<int, int>), map_var);
Run Code Online (Sandbox Code Playgroud)
因为形成函数类型会忽略额外的括号,所以您可以使用带有或不带括号的宏,其中类型名称不包含逗号:
FOO((int), int_var);
FOO(int, int_var2);
Run Code Online (Sandbox Code Playgroud)
当然,在C语言中,这不是必需的,因为类型名称不能包含括号外的逗号.因此,对于跨语言宏,您可以编写:
#ifdef __cplusplus__
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
#else
#define FOO(t,name) t name
#endif
Run Code Online (Sandbox Code Playgroud)
Mik*_*our 48
如果您的预处理器支持可变参数宏:
#define SINGLE_ARG(...) __VA_ARGS__
#define FOO(type,name) type name
FOO(SINGLE_ARG(std::map<int, int>), map_var);
Run Code Online (Sandbox Code Playgroud)
否则,它有点单调乏味:
#define SINGLE_ARG2(A,B) A,B
#define SINGLE_ARG3(A,B,C) A,B,C
// as many as you'll need
FOO(SINGLE_ARG2(std::map<int, int>), map_var);
Run Code Online (Sandbox Code Playgroud)
Che*_*Alf 27
只需定义FOO为
#define UNPACK( ... ) __VA_ARGS__
#define FOO( type, name ) UNPACK type name
Run Code Online (Sandbox Code Playgroud)
然后使用类型参数周围的括号来调用它,例如
FOO( (std::map<int, int>), map_var );
Run Code Online (Sandbox Code Playgroud)
在宏定义的注释中举例说明调用当然是个好主意.
| 归档时间: |
|
| 查看次数: |
33869 次 |
| 最近记录: |