问题描述
对于单个变量(或给定数量的变量),使用宏对变量进行字符串化很容易。例如。对于2个变量,我可以这样做:
For a single variable (or a given number of variables), it's easy to use macros to stringify variables. E.g. for 2 variables, I can do:
#define STRINGIFY(var1, var2) (std::string(#var1) + " " + #var2)
是否可以使用可变参数宏或其他一些扩展上述内容的方法某种编译时的技巧,最终得到一个 STRINGIFY
函数,该函数接受任意数量的参数?
Is there a way to extend the above with either variadic macros or some other sort of compile-time trickery, to ultimately get a STRINGIFY
function that accepts an arbitrary number of arguments?
推荐答案
我不确定我是否了解您要执行的操作。下面的代码在编译时标记 __ VA_ARGS __
。它不检查语法:它用'\0'
盲目替换空格和逗号,将标识符的开头存储在 arg
以及 argc
中的参数数量。
I'm not sure that I understood what you're trying to do. The code below tokenizes, at compile time, __VA_ARGS__
. It does not check the syntax: it blindly replaces the white-space and commas with '\0'
, stores the start of identifiers in arg
and the number of arguments in argc
.
#include <iostream>
template < unsigned N > constexpr
unsigned countarg( const char( &s )[N], unsigned i = 0, unsigned c = 0 )
{
return
s[i] == '\0'
? i == 0
? 0
: c + 1
: s[i] == ','
? countarg( s, i + 1, c + 1 )
: countarg( s, i + 1, c );
}
template < unsigned N > constexpr
unsigned skipid( char( &s )[N], unsigned i = 0 )
{
return s[i] == '\0' || s[i] == ' ' || s[i] == '\t' || s[i] == ','
? i
: skipid( s, i + 1 );
}
template < unsigned N, unsigned M > constexpr
unsigned tokenize( char( &s )[N], const char*(&a)[M], unsigned i = 0, unsigned j = 0 )
{
return s[i] == '\0'
? i
: s[i] == ' ' || s[i] == '\t' || s[i] == ','
? ((s[i] = '\0'),
tokenize( s, a, ++i, j ))
: ((a[j] = s + i),
i = skipid( s, i ),
tokenize( s, a, i, ++j ));
}
#define TOKENIZEVA( ... ) char orig[] = #__VA_ARGS__; const unsigned argc = countarg(#__VA_ARGS__); const char* arg[argc]; tokenize( orig, arg );
#define PRINT( ... ) { TOKENIZEVA(__VA_ARGS__) for ( auto s : arg ) std::cout << s << std::endl; }
int main()
{
PRINT( first, second, third, fourth );
return 0;
}
这篇关于字符串化任意数量的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!