Phylliida
Phylliida

Reputation: 4383

Is there a way to make a macro have different behavior if it has parenthesis?

I'm trying to do something like this:

#define FOO printf("No paren\n");
#define FOO(x) printf(x);

Is there a way to do this with c++ macros?

Upvotes: 4

Views: 168

Answers (3)

Steve Summit
Steve Summit

Reputation: 48043

No. A given macro name can either be plain ("object-like") or "function-like", not both.

Upvotes: 8

tahsmith
tahsmith

Reputation: 1723

I would not advise it, but it is possible with some help from C++ itself,

#include <iostream>

template<typename T>
struct CustomMessage
{
    const T& t;
    CustomMessage(const T& t) : t(t)
    {}
};

struct DefaultMessage
{
    template<typename T> CustomMessage<T> operator() (const T& t)
    {
        return {t};
    }
};
template<typename T>
std::ostream& operator<< (std::ostream& os, const CustomMessage<T>& message)
{
    return os << message.t;
}

std::ostream& operator<< (std::ostream& os, const DefaultMessage& message)
{
    return os << "no paren\n";
}

using namespace std;

#define FOO std::cout << DefaultMessage{}

int main() {
    int x = 42;
    FOO;
    FOO(x);
    return 0;
}

Live one Ideone https://ideone.com/VboP8R

Upvotes: 4

Chris Kitching
Chris Kitching

Reputation: 2655

Not so directly: A single macro has to either be "plain" or "function like".

However, you can sorta-kinda do some things in this direction.

You can use variadic macros and change behaviour based on the number of arguments.

You can use the above to build the name of a target macro to delegate to:

#define NUM_ARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N

#define NUM_ARGS(...) NUM_ARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)

#define CAKE_1(X) some-interesting-code-here
#define CAKE_2(X, Y) some-different-interesting-code-here
#define CAKE(...) CONCAT(CAKE_, NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)

In the above, calling CAKE() with 1 argument will invoke CAKE_1, and calling it with 2 will invoke CAKE_2.

Whether or not it's a good idea to do this sort of thing, for reasons of clarity and such, is left as an exercise for the reader.

Upvotes: 1

Related Questions