Search code examples
c++macrostype-deduction

Deduce the type of a declaration


I am writing a macro that takes a declaration as its single argument. Is it possible to deduce the type of the declaration inside the macro without splitting up the single argument into separate type and identifier arguments?

#define M(declaration) \
    declaration;       \
    static_assert(sizeof(/* deduce type of 'declaration' */) == 4, "!")

M(int i);
M(double d{3.14});
M(std::string s{"Hello, world!"});

The following implementation would work but it feels less user-friendly (imo):

#define M(type, identifier) \
    type identifier;        \
    static_assert(sizeof(type) == 4, "!")

M(int, i);
M(double, d{3.14});
M(std::string, s{"Hello, world!"});

If possible, I would prefer to take the declaration as a single argument.


Related question: Macro to get the type of an expression; but I failed to get that code to work in my example (compiler error: expected nested-name-specifier).


Solution

  • If your static assertion message is really that simple "!"1, I suggest you ditch the preprocessor. Make the type system work for you instead:

    namespace detail {
      template<typename T>
      struct check_declared_type {
        using type = T;
        static_assert(sizeof(type) == 4, "!");
      };
    }
    
    template<typename T>
    using M = typename detail::check_declared_type<T>::type;
    
    // .. Later
    
    int main() {
      M<int> i;
      M<double> d{3.14};
      M<std::string> s{"Hello, world!"};
    }
    

    1 - Specifically, if you don't need the preprocessor to stringify anything for you.