Writing preprocessor directives to get string
Can you write preprocessor directives to return you a std::string or char*?
For example: In case of integers:
#define square(x) (x*x)
int main()
{
int x = square(5);
}
I'm looking to开发者_JS百科 do the same but with strings like a switch-case pattern. if pass 1 it should return "One" and 2 for "Two" so on..
You don't want to do this with macros in C++; a function is fine:
char const* num_name(int n, char const* default_=0) {
// you could change the default_ to something else if desired
static char const* names[] = {"Zero", "One", "Two", "..."};
if (0 <= n && n < (sizeof names / sizeof *names)) {
return names[n];
}
return default_;
}
int main() {
cout << num_name(42, "Many") << '\n';
char const* name = num_name(35);
if (!name) { // using the null pointer default_ value as I have above
// name not defined, handle however you like
}
return 0;
}
Similarly, that square should be a function:
inline int square(int n) {
return n * n;
}
(Though in practice square isn't very useful, you'd just multiply directly.)
As a curiosity, though I wouldn't recommend it in this case (the above function is fine), a template meta-programming equivalent would be:
template<unsigned N> // could also be int if desired
struct NumName {
static char const* name(char const* default_=0) { return default_; }
};
#define G(NUM,NAME) \
template<> struct NumName<NUM> { \
static char const* name(char const* default_=0) { return NAME; } \
};
G(0,"Zero")
G(1,"One")
G(2,"Two")
G(3,"Three")
// ...
#undef G
Note that the primary way the TMP example fails is you have to use compile-time constants instead of any int.
A #define
preprocessor directive does substitute the string of characters in the source code. The case...when
construct you want is still not trivial:
#define x(i) ((i)==1?"One":((i)==2?"Two":"Many"))
might be a start -- but defining something like
static char* xsof[] = ["One", "Two", "Many"];
and
#define x(i) xsof[max(0, min((i)-1, (sizeof xsof / sizeof xsof[0] - 1)))]
seems more reasonable and better-performing.
Edit: per Chris Lutz's suggestion, made the second macro automatically adjust to the xsof
definition; per Mark's, made the count 1-based.
I have seen this...
#define STRING_1() "ONE"
#define STRING_2() "TWO"
#define STRING_3() "THREE"
...
#define STRING_A_NUMBER_I(n) STRING_##n()
#define STRING_A_NUMBER(n) STRING_A_NUMBER_I(n)
I belive this extra step is to make sure n is evaluated, so if you pass 1+2, it gets transformed to 3 before passed to STRING_A_NUMBER_I, this seems a bit dodge, can anyone elaborate?
You cannot turn integers into strings so 1 ---> "One", 2 ---> "Two", etc except by enumerating each value.
You can convert an argument value into a string with the C preprocessor:
#define STRINGIZER(x) #x
#define EVALUATOR(x) STRINGIZER(x)
#define NAME(x) EVALUATOR(x)
NAME(123) // "123"
#define N 123
#define M 234
NAME(N+M) // "123+234"
See also SO 1489932.
精彩评论