tags:

views:

111

answers:

4

Given:

#define f(x, y) (x+y)
#define g(x, y) (x*y)
#define A 1, 2
#define B 2, 3

int main() {
  int a = f(A);
  int b = g(A);
  int c = f(B);
  int d = g(B);
}

which does not work,

how can I make it work? The basic idea is that I have one list of arguments that I want to pass to two different macros, without repeating the list of long arguments every time.

Is there a way to do this? [You're welcome to modify f & g; you're even welcome to modify A & the way I call the macros. The only requirements are: 1) the arguemnt list can only appear once 2) it can't be hard coded ... so that I can call the macros with different arguments

If you're solution doesn't quite work but 'almost works' (for you definition of almost), I'd like to hear it too, perhaps I can fudge it to work.

Thanks!

Edit: f & g must be macros. They capture the symbol names and manipulate them.

+4  A: 

You could do this:

static int f(int x, int y) { return (x+y); }
static int g(int x, int y) { return (x*y); }
#define A 1, 2
#define B 2, 3

If you were using a C compiler that supported a nonstandard inline directive, you could eliminate the overhead of a function call. And if you were using C++,

template<T> T f(T x, T y) { return (x+y); }
template<T> t g(T x, T y) { return (x*y); }
#define A 1, 2
#define B 2, 3

which would work roughly the same as your intended C macro solution.

If f and g must be macros, there isn't any way with the C preprocessor to pass multiple arguments to the macros without an actual comma appearing at the invocation site. In order to do that, you would have to add a pre-preprocessor level above the C preprocessor.

Greg Hewgill
Nice solution. Additionally, even without the inline directive, as long as you use the static directive on the functions, optimizing compilers likely will inline automatically anyway.
Tall Jeff
"a nonstandard inline directive". For that matter if it supported the standard one, it probably would inline something this simple. We know the questioner is using C99, since his main function has no return statement, but presumably is intended to have defined behaviour ;-)
Steve Jessop
A: 

Maybe this is what you want:

#include<iostream>
using namespace std;

#define A 1, 2

template <typename T>
inline T f(T a, T b) { return a + b; }

int main()
{
    cout << f(A) << endl;
    return 0;
}
Vlad
Question is about C, isn't it?
Steve Jessop
+4  A: 

If you were using C99, you can use the compound initialiser syntax to do this by passing multiple arguments as a single array:

#define f(a) (a[0]+a[1])
#define g(a) (a[0]*a[1])
#define A ((int[]) {1, 2})
#define B ((int[]) {2, 3})

GCC supports this compound literal syntax in both C89 and C++ mode.

Greg Hewgill
Thx for sorting this out :)
mre
+2  A: 

EDIT: A version that works with unmodified A and B

#define f(x, y) (x+y) 
#define g(x, y) (x*y) 
#define A 1, 2 
#define B 2, 3

#define APPLY2(a, b) a b
#define APPLY(a, b) APPLY2(a, (b))

int main(int argc, char* argv[])
{
    int x= APPLY(f, A);
    int y= APPLY(f, B);
    int z= APPLY(g, A);
    int d= APPLY(g, B);

    return 0;
}
MSN
This is ingenious.Anyone that understands will upvote this answer.
anon
Why the extra indirection? `#define APPLY(a, b) a(b)` works just as well.
Chris Dodd
@Chris, it doesn't work that way. I forget the exact rason, but MSVC sure does complain about it.
MSN