Recursive macro processor for strings

I have code that mostly needs Unicode strings, but I want to make it conditional (i.e. TEXT("string") expands to L"string" or "string" , depending on the settings). For this, I use a macro:

 #ifdef _UNICODE # define VSTR(str) L##str #else # define VSTR(str) str #endif 

The main complication of this is printf format strings, which use %s and %s for strings with the same encoding and different encodings, respectively. Some strings come from similar conditional APIs ( TCHAR and similar), while some of them relate to a set of APIs (mainly C strings). When using _tprintf and the family, the function used may change, making the conditions %s and %s conditional, and they may need to be reversed. To handle this, I defined macros for the corresponding format elements:

 #ifdef _UNICODE # define VPFCSTR(str) "%S" # define VPFWSTR(str) "%s" # define VPFTSTR(str) VPFWSTR(str) #else # define VPFCSTR(str) "%s" # define VPFWSTR(str) "%S" # define VPFTSTR(str) VPFCSTR(str) #else 

Now everything works fine, but the syntax forces:

 VSTR("Beginning of a format string, with a string '") VPFTSTR VSTR("' included.") 

I would like to be able to use syntax like:

 VSTR("Beginning of a format string, with a string '", VPFTSTR, "' included.") 

For Unicode, this needs to be expanded to:

 L"Beginning of a format string, with a string '" L"%s" L"' included." 

The only complication is a variable number of arguments, all of which must be converted in the same way (as needed).

My first idea was to use __VA_ARGS__ to handle this using empty arguments, like this:

 VASTR(str, ...) VSTR(str) VASTR(__VA_ARGS__) 

Unfortunately, since macros cannot be used in their own definition, this fails. Then I tried the proxy:

 VASTR2(...) VASTR(__VA_ARGS__) VASTR(str, ...) VSTR(str) VASTR2(__VA_ARGS__) 

The proxy method also does not work.

Is there a way to handle running the same macro for each macro argument (zero) that takes a variable number of arguments? Or, if not, is there an equivalent? If specific to the compiler, MSVC10 is preferred, but all of this is of interest.

+4
source share
2 answers

Recursive macro expansion is not possible in C / C ++.

Not sure, but C ++ 0x allows you to skip the encoding prefix to concatenate string literals. Thus, you can try to create your macro to add L only to the first string literal and use it as follows:

 VSTR("Beginning of a format string, with a string '" VPFTSTR "' included.") 

Please correct me if I am wrong.

UPD

A similar question related to Unicode: What happens to the adjacent concatenation of string literals when there is a modifier (L, u8, etc.)

+4
source

Using the Boost.Preprocessor library and these additional macros, you can apply your VSTR macro to each argument:

 //Your VSTR macro for one argument #define VSTR_EACH(str) ... /** * PP_NARGS returns the number of args in __VA_ARGS__ */ #define PP_NARGS(...) \ PP_DETAIL_NARG((__VA_ARGS__,PP_DETAIL_RSEQ_N())) #define PP_DETAIL_NARG(args) \ PP_DETAIL_ARG_N args #define PP_DETAIL_ARG_N( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N #define PP_DETAIL_RSEQ_N() \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9,8,7,6,5,4,3,2,1,0 //Convert agruments list to a BOOST_PP_SEQ so we can iterate over it //This is two macros in order to avoid the bug in MSVC compilers #define DETAIL_PP_ARGS_TO_SEQ(size, tuple) BOOST_PP_TUPLE_TO_SEQ(size, tuple) #define PP_ARGS_TO_SEQ(...) DETAIL_PP_ARGS_TO_SEQ(PP_NARGS(__VA_ARGS__), (__VA_ARGS__)) //The macro used inside of BOOST_PP_SEQ_FOR_EACH #define VSTR_SEQ_EACH(t, data, x) VSTR_EACH(x) #define VSTR(...) BOOST_PP_SEQ_FOR_EACH(VSTR_SEQ_EACH, ~, PP_ARGS_TO_SEQ(__VA_ARGS__)) 
+1
source

Source: https://habr.com/ru/post/1387973/


All Articles