2

I use macros to concatenate strings, such as:

#define STR1 "first"
#define STR2 "second"

#define STRCAT(A, B) A B

which having STRCAT(STR1 , STR2 ) produces "firstsecond".

Somewhere else I have strings associated to enums in this way:

enum class MyEnum
{
    Value1,
    Value2
}
const char* MyEnumString[] =
{
    "Value1String",
    "Value2String"
}

Now the following does not work:

STRCAT(STR1, MyEnumString[(int)MyEnum::Value1])

I was just wondering whether it possible to build a macro that concatenate a #defined string literal with a const char*? Otherwise, I guess I'll do without macro, e.g. in this way (but maybe you have a better way):

std::string s = std::string(STR1) + MyEnumString[(int)MyEnum::Value1];
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mauro Ganswer
  • 1,379
  • 1
  • 19
  • 33
  • 1
    why do you want to use macros so badly? You know they are strongly discouraged in C++? – tenfour May 31 '14 at 10:32
  • @tenfour sincerely I didn't know (as I'm not an expert of C++). So you would suggest to avoid even the STRCAT(STR1, STR2) macro? Can you please give more details on what could be the drawbacks on using it? – Mauro Ganswer May 31 '14 at 12:03
  • See here for a good answer: http://stackoverflow.com/a/14041847/402169. But for me the better question is: Why use a macro when you can use a function? – tenfour May 31 '14 at 12:14
  • thanks for the link. Well in my case I make sure my macro cannot clash with other names (macro names are prefixed) and I use them only for strings, which give the name to variable in my IO dll that is also used by other users. An alternative as you said might be to provide functions that return the variable names, maybe by taking an enum as input. I will think whether it's worth to switch to this solution. – Mauro Ganswer May 31 '14 at 12:50

3 Answers3

3

The macro works only on string literals, i.e. sequence of characters enclosed in double quotes. The reason the macro works is that C++ standard treats adjacent string literals like a single string literal. In other words, there is no difference to the compiler if you write

"Quick" "Brown" "Fox"

or

"QuickBrownFox"

The concatenation is performed at compile time, before your program starts running.

Concatenation of const char* variables needs to happen at runtime, because character pointers (or any other pointers, for that matter) do not exist until the runtime. That is why you cannot do it with your CONCAT macro. You can use std::string for concatenation, though - it is one of the easiest solutions to this problem.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

It's only working for char literals that they can be concatenated in this way:

 "A" "B"

This will not work for a pointer expression which you have in your sample, which expands to a statement like

 "STR1" MyEnumString[(int)MyEnum::Value1];

As for your edit:
Yes I would definitely go for your proposal

 std::string s = std::string(STR1) + MyEnumString[(int)MyEnum::Value1];
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

Your macro is pretty unnecessary, as it can only work with string literals of the same type. Functionally it does nothing at all.

std::string s = STRCAT("a", "b");

Is exactly the same as:

std::string s = "a" "b";

So I feel that it's best to just not use the macro at all. If you want a runtime string concatenating function, a more C++-canonical version is:

inline std::string string_concat(const std::string& a, const std::string& b)
{
    return a + b;
}

But again, it seems almost pointless to have this function when you can just do:

std::string a = "a string";
std::string ab = a + "b string";

I can see limited use for a function like string_concat. Maybe you want to work on arbitrary string types or automatic conversion between UTF-8 and UTF-16...

tenfour
  • 36,141
  • 15
  • 83
  • 142