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!!
Related
I'm having an issue removing expressions from a QString using QRegExp. I tried a countless number of regex to no avail. What am I doing wrong?
Sample Text (QString myString) In this instance, myString contains "\u0006\u0007\u0013Hello".
myString.remove(QRegExp("\\[u][0-9]{4}"));
It does not remove any instances of \uXXXX where X = numbers.
However, when I am specific such as:
myString.remove("\u0006");
It does remove it.
String literals are not always the same as character sequence
for (char c : "\u0006\u0007\u0013Hello".toCharArray()) {
System.out.println( c + " (" + (int)c + ")" );
}
System.out.println( "--------------" );
for (char c : "\\u0006\\u0007\\u0013Hello".toCharArray()) {
System.out.println( c + " (" + (int)c + ")" );
}
In the first example \u0006 is encoding an unicode code point, whereas in second the string actually contains a backslash.
The string literal only exist at compile time, at runtime they are character sequences.
Regexes are working over character sequence not over string litteral, and also backlash have special meaning and need to be escaped.
Also note that \u0041 is another way to encode A.
Maybe what you are looking for are unicode categories, maybe following can help:
string.replaceAll( "\\p{Cc}", "" )
I got hand over some legacy code and first I want to change
(int)a + b;
into
static_cast<int>(a) + b;
There are a lot of them and doing them manually is very time consuming. Is there a way to use vim to make this happen?
I tried something like
:%s/\(int\).* /static_cast<int>(\2)/g
but it doesn't work. Please advice.
Try this:
:%s/(\(.*\))\([^ ]*\)/static_cast<\1>(\2)/g
This regex, as per your question, assumes that there will be a space after the variable name:
Example:
For following test data:
(int)a + b
(float)x * y
(int)z+m
result will be
static_cast<int>(a) + b
static_cast<float>(x) * y
static_cast<int>(z+m)
Explaining the regex
(\(.*\)) - Match whatever is inside () and capture it
\([^ ]*\) - followed by anything which is not a space and capture it
You can use this:
%s/(int)\(a\)/static_cast<int>(\1)/g
This is assuming variable name always is a. If it is not then you can replace a with [a-z].
I have several mappings for this task in lh-cpp.
In that case, it'll be ,,sc, or ,,rc, or ,,dc. (here, , is actually my <localleader>).
It's actually implemented as:
function! s:ConvertToCPPCast(cast_type)
" Extract text to convert
let save_a = #a
normal! gv"ay
" Strip the possible brackets around the expression
let expr = matchstr(#a, '^(.\{-})\zs.*$')
let expr = substitute(expr, '^(\(.*\))$', '\1', '')
"
" Build the C++-casting from the C casting
let new_cast = substitute(#a, '(\(.\{-}\)).*',
\ a:cast_type.'<\1>('.escape(expr, '\&').')', '')
" Do the replacement
exe "normal! gvs".new_cast."\<esc>"
let #a = save_a
endfunction
vnoremap <buffer> <LocalLeader><LocalLeader>dc
\ <c-\><c-n>:'<,'>call <sid>ConvertToCPPCast('dynamic_cast')<cr>
nmap <buffer> <LocalLeader><LocalLeader>dc viw<LocalLeader><LocalLeader>dc
...
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.
#include <iostream>
int main() {
std::string s = "?????";
std::cout << s << std::flush;
}
What should I write in the s variable to output \"\"' (these 5 characters?)
Escape them like this (prepend \ to each of the special characters):
"\\\"\\\"'"
The other option is C++11 raw string literal:
R"(\"\"')"
Since C++11, you can put whatever characters you like in a raw string literal:
R"(\"\"')"
Historically, you would have to escape \ and " with \ in a normal string literal:
"\\\"\\\"'"
You need to escape the \ and " characters with \
std::string s = "\\\"\\\"'";
In C++11, you can also use a raw string literal
R"(\"\"')"
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 #