Working with extra brackets in macros in MSVC

There are some cases where you need to (a) have a macro that (b) brackets one of its arguments in (c) the case where the language does not allow brackets.

A simple example:

#define MAKE_STRUCT(name, base) struct name : base { }

struct X { };
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // error

This is a mistake because we expect a type name and get (. ecatmur provides a smart workaround for this, using the fact that there are other parts of the language that allow you to add an extra set of parentheses:

template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };

#define MAKE_STRUCT(name, base) struct name : argument_type<void(base)>::type { }

struct X { };
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok

This is compilation on gcc and clang, but it does not compile on MSVC. Is there any trick specific to MSVC for using parentheses or another trick that works on all three compilers?

, , ( , Catch2 TEST_CASE_METHOD()).

+4
2

, , , . , v++, g++ clang++ , , , .

#define MAKE_STRUCT(name, base) struct name: EXPAND1(DEF base) {}
#define EXPAND1(param) EXPAND2(param)
#define EXPAND2(param) NO## param
#define DEF(param) DEF param
#define NODEF

struct X { };
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok

-

+4

, , , :

struct tag {};

#define MAKE_STRUCT(name, base) struct name : \
  decltype(base(tag{})) { };

struct X {
     X(tag );
     X() = default;
};

MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok
0

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


All Articles