3

Supposedly, I have a variadic macro (e.g., MY_MACRO(...)) and I call it the following way:

MY_MACRO(std::pair<int, int> const &p)

Now, __VA_ARGS__ in my macro's body would be std::pair<int, int> const &p.

Is there a way to figure out the type of __VA_ARGS__?

Presumably, I would be grateful if something like decltype(std::pair<int, int> const &p) worked and yield std::pair<int, int> const&, so in my variadic macro's body decltype(__VA_ARGS__) would yield std::pair<int, int> const& as well. Unfortunately this doesn't work.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
101010
  • 41,839
  • 11
  • 94
  • 168

1 Answers1

5

You can use __VA_ARGS__ as a lambda parameter, then convert that lambda to a function pointer and extract the parameter type:

template <typename T> struct func_param {};
template <typename T> struct func_param<void(*)(T)> {using type = T;};

#define FOO(...) \
    do \
    { \
        auto lambda = +[]([[maybe_unused]] __VA_ARGS__) {}; \
        using type = func_param<decltype(lambda)>::type; \
        /* Do something with `type`. */\
    } \
    while (0);
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Note using [the fact that lambda w/o capture can be converted to function pointer](https://stackoverflow.com/q/28746744/1708801) – Shafik Yaghmour Oct 03 '18 at 22:55
  • Yes, and also the trick that applying unary `+` to such a lambda forces the conversion, since there is no overloaded `operator+` matching the lambda type, but the pointer to function is a valid operand of the built-in meaning of unary `+`. – aschepler Oct 03 '18 at 23:08