4

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?

Phylliida
  • 4,217
  • 3
  • 22
  • 34

3 Answers3

8

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

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
4

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

tahsmith
  • 1,643
  • 1
  • 17
  • 23
1

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.

Community
  • 1
  • 1
Chris Kitching
  • 2,559
  • 23
  • 37
  • 1
    Downvoted as this answers `CAKE(x)` vs `CAKE(x, y)` ... rather than the actual question of `CAKE` vs `CAKE(x)` – donkopotamus Mar 08 '16 at 23:06
  • Did you try reading the first sentence, in which I explain that's impossible? – Chris Kitching Mar 08 '16 at 23:20
  • Sorry for giving OP a nearby alternative when they ask for an impossible thing, I guess? – Chris Kitching Mar 08 '16 at 23:20
  • Thanks, yea I was playing with variadic macros like you explained here (you can also do 0 argument ones) but that wasn't quite what I was looking for. – Phylliida Mar 09 '16 at 02:10
  • Indeed, you can't do exactly what you want using just the preprocessor, but tahsmith's answer is a quite interesting hybrid approach (One that also illustrates quite nicely why doing this is a _terrible_ idea). What do you want this for anyway? – Chris Kitching Mar 09 '16 at 02:12
  • A friend was defining custom integrators (so he didn't manually have to define thousands of them) and wanted this for some reason - I dunno, he just mentioned it to me and I thought it was a fun challenge – Phylliida Mar 09 '16 at 02:19