我正在尝试编写一个程序,其中一些函数的名称依赖于某个宏变量的值,宏如下:
#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE
int NAME(some_function)(int a);
Run Code Online (Sandbox Code Playgroud)
不幸的是,宏NAME()
将其转化为
int some_function_VARIABLE(int a);
Run Code Online (Sandbox Code Playgroud)
而不是
int some_function_3(int a);
Run Code Online (Sandbox Code Playgroud)
所以这显然是错误的方式.幸运的是,VARIABLE的不同可能值的数量很小所以我可以简单地做一个#if VARIABLE == n
并单独列出所有情况,但我想知道是否有一个聪明的方法来做到这一点.
这是我想要做的:
typedef enum { ONE, TWO, THREE } Numbers;
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个函数来执行类似于以下的切换案例:
char num_str[10];
int process_numbers_str(Numbers num) {
switch(num) {
case ONE:
case TWO:
case THREE:
{
strcpy(num_str, num); //some way to get the symbolic constant name in here?
} break;
default:
return 0; //no match
return 1;
}
Run Code Online (Sandbox Code Playgroud)
而不是在每种情况下定义,有没有办法使用枚举变量设置它,就像我在上面尝试做的那样?
#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
Run Code Online (Sandbox Code Playgroud)
上面这行来自虚幻4,我知道我可以在不真实的论坛上问过它,但我认为这是一个普遍的C++问题,值得在这里提出.
我理解第一行定义了一个宏,但是我不熟悉C++中的预处理器恶作剧,所以我迷失在那里.逻辑告诉我反斜杠意味着声明继续到下一行.
FThreadSafeStaticStat看起来有点像模板,但是那里正在进行#和C++中我从未见过的语法
有人能告诉我这意味着什么吗?我知道您可能无法访问Unreal 4,但这只是我不理解的语法.
我正在整理一些旧的代码,这些代码使用"幻数"来设置硬件寄存器,我想使用常量而不是这些数字来使代码更具表现力(实际上它们将映射到名称/用于记录寄存器的值).
但是,我担心随着变化的数量,我可能会打破神奇的数字.这是一个简化的例子(寄存器集更复杂):
const short mode0 = 0;
const short mode1 = 1;
const short mode2 = 2;
const short state0 = 0;
const short state1 = 4;
const short state2 = 8;
Run Code Online (Sandbox Code Playgroud)
而不是:
set_register(5);
Run Code Online (Sandbox Code Playgroud)
我们有:
set_register(state1|mode1);
Run Code Online (Sandbox Code Playgroud)
我正在寻找的是构建时间版本:
ASSERT(5==(state1|mode1));
Run Code Online (Sandbox Code Playgroud)
更新
@Christian,感谢快速响应,我对C/non-boost环境的答案感兴趣,因为这是驱动程序/内核代码.
我正在看一个定义了大量常量数组的应用程序.让我感到困惑的是在宏观中使用彼此相邻的两个磅标志.例如:
#define r0(p,q,r,s) 0x##p##q##r##s
Run Code Online (Sandbox Code Playgroud)
那两个磅标志是什么意思?
在:C++ FAQ - 其他技术问题 - [39.6]对于需要将两个令牌粘贴在一起的宏应该怎么做?
有人可以向我解释原因吗?我所读到的只是相信我,但我不能仅仅相信某事,因为有人这么说.
我尝试了这种方法,但我找不到任何错误:
#define mymacro(a) int a ## __LINE__
mymacro(prefix) = 5;
mymacro(__LINE__) = 5;
int test = prefix__LINE__*__LINE____LINE__; // fine
Run Code Online (Sandbox Code Playgroud)
那么为什么我需要这样做呢(引自网页):
但是,当您使用##时,需要双层间接.基本上你需要为"令牌粘贴"创建一个特殊的宏,例如:
Run Code Online (Sandbox Code Playgroud)#define NAME2(a,b) NAME2_HIDDEN(a,b) #define NAME2_HIDDEN(a,b) a ## b
相信我 - 你真的需要这样做!(并且请没有人写信给我说它有时可以在没有第二层间接的情况下工作.尝试用__ LINE__连接一个符号然后看看会发生什么.)
编辑:有人也可以NAME2_HIDDEN
在下面宣布之前解释他为什么使用?NAME2_HIDDEN
在使用宏之前定义宏似乎更合乎逻辑.这是某种伎俩吗?
C 预处理器具有称为stringification的功能。这是一项允许从宏参数创建(窄)字符串文字的功能。它可以像这样使用:
#define PRINTF_SIZEOF(x) printf("sizeof(%s) == %d", #x, sizeof(x))
/* stringification ^^ */
Run Code Online (Sandbox Code Playgroud)
用法示例:
PRINTF_SIZEOF(int);
Run Code Online (Sandbox Code Playgroud)
...可能会打印:
sizeof(int) == 4
Run Code Online (Sandbox Code Playgroud)
如何从宏参数创建宽字符串文字?换句话说,我该如何实施WPRINTF_SIZEOF
?
#define WPRINTF_SIZEOF(x) wprintf( <what to put here?> )
Run Code Online (Sandbox Code Playgroud) 为什么代码:
#define EXPONENT(num, exp) num ## e ## exp
EXPONENT(1,1)
EXPONENT(1,-1)
EXPONENT(1,+1)
Run Code Online (Sandbox Code Playgroud)
预处理后的更改为:
1e1
1e- 1
1e+ 1
Run Code Online (Sandbox Code Playgroud)
而不是
1e1
1e-1
1e+1
Run Code Online (Sandbox Code Playgroud)
?我怀疑它可能是因为-1,+ 1被解析为两个标记(?).但是,在这种情况下如何获得后者的结果呢?
我需要更换
GET("any_name")
Run Code Online (Sandbox Code Playgroud)
同
String str_any_name = getFunction("any_name");
Run Code Online (Sandbox Code Playgroud)
困难的部分是如何修剪引号.可能?有任何想法吗?
在C++ 11或更高版本中是否有某种方法可以实现类似的行为:
int some_int;
std::string x=variable_name<some_int>::value; //Theoretical code
std::cout << x;
Run Code Online (Sandbox Code Playgroud)
结果应该是:
some_int
如果没有,是否有编译器特定的方法来做到这一点?我的目标是MSVS.
c ×7
c++ ×5
macros ×2
assert ×1
c++11 ×1
compile-time ×1
enums ×1
refactoring ×1
string ×1
token ×1
visual-c++ ×1