Concatenating #define in C++ - c++

I have something like:
#define BASE_FOLDER = "Resources"
#define PREFERENCE_FILE_NAME = "AppPreferences.txt"
#define SPLASH_FILE_NAME = "Splash.png"
#define PREFERENCE_PATH = ".\\" + BASE_FOLDER + "\\" + PREFERENCE_FILE_NAME
#define SPLASH_PATH = ".\\" + BASE_FOLDER + "\\" + SPLASH_FILE_NAME
and the compiler is throwing errors where PREFERENCE_PATH is used.
expecting primary expression before = token.
These all worked when I was doing
#define PREFERENCE_PATH = ".\\Resources\\AppPreferences.txt"
#define SPLASH_PATH = ".\\Resources\\Splash.png"
What am I doing wrong?

Get rid of the equal signs. Preprocessor definitions don't use equal signs.
Then get rid of the pluses. String literals are concatenated when you put them side by side without a plus in between. Emphasis on literals because this is a compile-time feature that only works with double-quoted literals, as in "foo" "bar" → "foobar". It doesn't work with variables.
#define BASE_FOLDER "Resources"
#define PREFERENCE_FILE_NAME "AppPreferences.txt"
#define SPLASH_FILE_NAME "Splash.png"
#define PREFERENCE_PATH ".\\" BASE_FOLDER "\\" PREFERENCE_FILE_NAME
#define SPLASH_PATH ".\\" BASE_FOLDER "\\" SPLASH_FILE_NAME

You can't concatenate strings (char* that is) in C++ like that...there is no + operator for them.

Related

How to use a string literal as a macro argument?

My question is the inverse of this question.
I want to write a macro that will accept an integer and a string literal as it's arguments, like so:
#define STRING_MAP_ENTRY(value, name) \
{value, std::to_string(val) + " - " + name}
STRING_MAP_ENTRY(0, "ENTRY_1")
The macro should turn the above call into {0, "0 - ENTRY_1"}
Is there a way to do this? My current attempt is this:
#define STRING_MAP_ENTRY(val, name) \
{ val, std::to_string(val) + "(" + name + ")" }
Something like this could work:
#define STRING_MAP_ENTRY(value, name) \
{value, #value " - " #name}
STRING_MAP_ENTRY(0, ENTRY_1)
the # before a token will stringify it. As for combining them, adjacent string literals will be combined into a single string.
Why do you want to use macro?
It's not good.
Use this:
auto STRING_MAP_ENTRY(int value_,string name_){
struct{int value;string name;} pair_{value_,to_string(value_)+string(" - ")+name_};
return pair_;
}
And use this to check if it works:
auto aa= STRING_MAP_ENTRY(0,string("ENTRY_1"));
cout<<aa.value<<','<<aa.name<<endl; // 0,0 - ENTRY_1
Remember:
Always use FUNCTION not MACRO!!

std::to_string is not declared compile error in aix

I am compiling my code in AIX env.. it givs me error "std::to_string" is not declared
successfully compiled same code in Windows.
define LOG_MSG(message) CLogManager::LogMessage(CLogManager::CurrentDateTime() + " - " + std::string(__FILE__) + "[" + std::to_string(static_cast<_ULonglong>(__LINE__)) + "] : " + std::string(message) + "\n")
This is the macro and i am using this as
LOG_MSG(" ** BEGIN StorePasswordFromFile()");
This macro is for logging purpose
I'm not sure how much support the latest xlC 14.1 (or whatever version you're using) has for std::to_string().
If the support is incomplete, C has a hideous double macro method (a) of turning __LINE__ into a C-string so that you can just use std::string, the same as you have for the __FILE__ and message items, and it appears the C++ pre-processor has stayed faithful to its hideous roots :-)
The code:
#include <stdio.h>
#define STR1(x) # x
#define STR2(x) STR1(x)
int main(void) {
char x[] = __FILE__;
char y[] = STR2(__LINE__);
printf("file = %s, line = %s\n",x,y);
return 0;
}
outputs:
file = qq.c, line = 6
showing that the __LINE__ has been successfully morphed into a C-string value.
You should be able to use a similar method in your macro:
#define STR1(x) # x
#define STR2(x) STR1(x)
#define LOG_MSG(message) CLogManager::LogMessage( \
CLogManager::CurrentDateTime() + " - " + \
std::string(__FILE__) + "[" + \
std::string(STR2(__LINE__)) + "] : " + \
std::string(message) + "\n")
int main() {
LOG_MSG ("My hovercraft is full of eels");
return 0;
}
Pre-processing that with g++ -E qq.cpp gives you:
CLogManager::LogMessage( CLogManager::CurrentDateTime() + " - " + std::string("qq.cpp") + "[" + std::string("10") + "] : " + std::string("My hovercraft is full of eels") + "\n");
(showing relevant line only) which seems to match what you want.
As a side note however, since you seem to be okay adding C-strings like "[" without needing to construct strings explicitly, I'm not sure that you need the std::string() calls at all for those. You still need the C macro hack to turn the integer into a C-string but, once that's been done, you should just be able to use that as-is.
Changing the final macro to:
#define LOG_MSG(message) CLogManager::LogMessage( \
CLogManager::CurrentDateTime() + " - " + \
__FILE__ + "[" + \
STR2(__LINE__) + "] : " + \
message + "\n")
will give you:
CLogManager::LogMessage( CLogManager::CurrentDateTime() + " - " + "qq.cpp" + "[" + "10" + "] : " + "My hovercraft is full of eels" + "\n");
Whether that's a good idea, I'll leave to the wider community but it at least gets around your immediate problem. I'd probably place the whole lot inside an #if/#else/#endif so that C++11 compilers that know about std::to_string() can use the more accepted approach.
(a) If you're interested in why this works, I'll explain below.
The # and ## macro operators actually take precedence over the recursive nature of macro replacement, as per C11 6.10.3.4 /1:
After all parameters in the replacement list have been substituted and # and ##
processing has taken place, all placemarker preprocessing tokens are removed. The
resulting preprocessing token sequence is then rescanned, along with all subsequent
preprocessing tokens of the source file, for more macro names to replace.
That means that the code:
#define STR(x) # x
STR(__LINE__)
will actually result in "__LINE__" because the # happens first and, once that's happened, the __LINE__ within the string literal is not subject to further replacement. By doing the two-step process:
#define STR1(x) # x
#define STR2(x) STR1(x)
STR2(__LINE__)
the first level of replacement turns STR2(__LINE__) into STR1(3) because __LINE__ on its own is subject to expansion.
Then the second level turns STR1(3), via # 3, into "3".
Perhaps the following may help:
#define STR1(x) # x
#define STR2a(x) STRn(x)
#define STR2b(x) STR1(x)
STR1(__LINE__)
STR2a(__LINE__)
STR2b(__LINE__)
The output of that, annotated, is:
"__LINE__" - stringise, no further processing of __LINE__ inside literal.
STRn(6) - shows first stage of replacement, line number replacement.
"7" - shows full process.

base file name from __FILE__

I need the file name only where the __FILE__ and __FILEW__ macros return the whole path.
I defined the following:
#define __FILE_NAME_ONLY__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
I am using it as follows:
#define MY_TRACE( mask, format, ... ) \
GlobalTrace( mask, L"-[" __FILE_NAME_ONLY__ L":" format , __VA_ARGS__ )
I get the following error:
error C2064: term does not evaluate to a function taking 1 arguments
and when I try the following macros:
#define __WIDE(_String) L ## _String
#define _WIDE(_String) __WIDE(_String)
as follows
#define MY_TRACE( mask, format, ... ) \
GlobalTrace( mask, L"-[" _WIDE(__FILE_NAME_ONLY__) L":" format , __VA_ARGS__ )
I get : error C2146: syntax error : missing ')' before identifier 'L' when I actually try to use the MY_TRACE macro
what am I missing? Thanks
You're depending on string literal concatenation, except that all of the terms aren't string literals.
I assume you were previously doing it like so:
#define MY_TRACE( mask, format, ... ) \
GlobalTrace( mask, L"-[" __FILE__ L":" format , __VA_ARGS__ )
If __FILE__ and format expand to a string literal, the 4 strings get pasted together into one. "A" "B" "C" "D" is the same as "ABCD".
That doesn't happen when you replace with __FILE_NAME_ONLY__ because it expands to a function call, not a literal.
If you're using gcc this macro should help:
__BASE_FILE__
Here's a helpful list

De-duplication of NSString & unichar constants

I have two simple constants:
NSString and
unichar,
defined as follows:
static NSString * const string = #"\u2022";
static unichar const character = 0x2022;
I'd want to have the number 0x2022 defined in one place.
I tried a lot of combinations (# and ##, also CFSTR macro) with no success.
Can it be done?
(Using ideas from How to concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?):
#define STRINGIFY(_x_) #_x_
#define UNICHAR_FROM_HEXCODE1(_c_) 0x ## _c_
#define UNICHAR_FROM_HEXCODE(_c_) UNICHAR_FROM_HEXCODE1(_c_)
#define NSSTRING_FROM_HEXCODE1(_c_) #"" STRINGIFY(\u ## _c_)
#define NSSTRING_FROM_HEXCODE(_c_) NSSTRING_FROM_HEXCODE1(_c_)
#define MYCHARCODE 2022
static unichar const character = UNICHAR_FROM_HEXCODE(MYCHARCODE);
static NSString * const string = NSSTRING_FROM_HEXCODE(MYCHARCODE);
Preprocessed output:
static unichar const character = 0x2022;
static NSString * const string = #"" "\u2022";
(Note that #"" "\u2022" is equivalent to #"\u2022".)

Macro String with variable

I don't know how to define a macro string with variable, like this:
#define str(x) "file x.txt", that mean I desire that str(1) refers to "file 1.txt".
However, in the case, str(1) or any number refers to "file x.txt", because x is an character.
Is there any way to solve this?
Concatenate the strings:
#define STR(x) "file " #x ".txt"
This makes use of a lexical feature of the two languages: adjacent string literals are concatenated; see both C++11 2.2/6 and C11 5.1.1.2/6:
Adjacent string literal tokens are concatenated.
#define str(x) ("file " #x ".txt")
using the stringification operator #