Reputation: 4383
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
Reputation: 48043
No. A given macro name can either be plain ("object-like") or "function-like", not both.
Upvotes: 8
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
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