0

I am looking for a way to call the same function (with different parameters) without knowing the function name. Something like this:

void my_func(int x)
{
    //...
    SELF(x-5);
    //...
}

I need to use the above because I have some complex macros. An example of why I need this:

#define start_func if(id == 0) return SELF();

int A(int id) { start_func /*...*/ }
int B(int id) { start_func /*...*/ }
int C(int id) { start_func /*...*/ }
int D(int id) { start_func /*...*/ }
int E(int id) { start_func /*...*/ }
int F(int id) { start_func /*...*/ }

int A() { /*...*/ }
int B() { /*...*/ }
int C() { /*...*/ }
int D() { /*...*/ }
int E() { /*...*/ }
int F() { /*...*/ }
MATH000
  • 1,043
  • 3
  • 13
  • 24
  • 1
    I don't understand why my question was down-voted? – MATH000 Jul 08 '16 at 20:01
  • What do you mean? Are you asking if you can call a function in itself (this is called a recursive function, and you can), or are you asking if you can call another function multiple times (if so, use a for loop)? Edit: Just saw your comment, I didn't downvote but I'd assume someone thought it was unclear probably – Shawn Jul 08 '16 at 20:02
  • This question is ridiculous. I have not explained ANYTHING about it and about the problem with your code. – Mattia F. Jul 08 '16 at 20:02
  • how can you not know the function name? it's right there on the first line of code you posted. Unless you're writing a closure, you always have to know/specify the name of the function. – Marc B Jul 08 '16 at 20:02
  • @Marc B I don't know the name because I am using macros. – MATH000 Jul 08 '16 at 20:04
  • 4
    It may help to show an actual example where you need to call the function but you do not know its name. – NathanOliver Jul 08 '16 at 20:04
  • 1
    then you should show the macros you're using. – Marc B Jul 08 '16 at 20:05
  • I don't even dare to hint that setjmp / longjmp can do this as long as arguments are non-const :D. – lorro Jul 08 '16 at 20:05
  • Short answer: I don't think you can do this portably. However, if you can show us why you need the macro, we might be able to show you a better way than using the macro. – md5i Jul 08 '16 at 20:07
  • @lorro `longjmp` is like `goto`². It leads to a lot of FUN. – Revolver_Ocelot Jul 08 '16 at 20:07
  • @all added example – MATH000 Jul 08 '16 at 20:10
  • 3
    The simple solution is to make the macro take the function name as a parameter. So `int A(int id) { start_func(A) /*...*/ }`. – David Schwartz Jul 08 '16 at 20:20
  • @David Schwartz This **is** a solution but isn't there any better way? – MATH000 Jul 08 '16 at 20:21
  • 4
    Another good reason to not use macros. I feel sorry for a person debugging and maintaining the code – Ed Heal Jul 08 '16 at 20:22
  • 2
    See http://stackoverflow.com/questions/15305310/predefined-macros-for-function-name-func – kfsone Jul 08 '16 at 20:23
  • @kfsone this will return the name of the function as string, right? Is there any way to use that string to call the function? – MATH000 Jul 08 '16 at 20:24
  • I was actually trying to underline the lack of a standard way to get the "current function name" at the pre-processor stage. I hit return too soon. – kfsone Jul 08 '16 at 20:26
  • @kfsone OK, thanks for the help! :D – MATH000 Jul 08 '16 at 20:26
  • 4
    Why not to pass a pointer to the function as one of the parameters and call that pointer inside the function? – Outtruder Jul 08 '16 at 20:34
  • @Outtruder Because this is not an elegant way to do the job. But it's simple and it works. – MATH000 Jul 08 '16 at 20:36
  • 1
    Looking at your example: Why are you abusing overloading in this way, rather than simply using default arguments: `int A (int id = 0) { if (id == 0) { /* default/zero code */ } else { /* non-zero code */ } }`? – acwaters Jul 08 '16 at 20:42
  • @acwaters Because the code is doing something completely different. – MATH000 Jul 08 '16 at 20:43
  • if it is doing something completely different then why does `A(int)` and `A` even have the same name? – 463035818_is_not_an_ai Jul 08 '16 at 20:47
  • 1
    @MATH000 Wait, do you mean that in the example, `A(int)` and `A()` do completely different things -- in which case, why are they named the same and disambiguated by only a parameter? -- or that the example is not indicative of your actual problem -- in which case, why bother writing it if it doesn't help us help you? Anyway, there is no way to do what you're asking. Why don't you show us your *actual* code so that we can help you find an alternate solution that doesn't involve complex macros or nonexistent preprocessor directives? – acwaters Jul 08 '16 at 20:47
  • @tobi303 There is good reason. Basically the A() function needs the results of the A(1), A(2) etc functions to work. – MATH000 Jul 08 '16 at 20:48
  • @acwaters This is my actual code. – MATH000 Jul 08 '16 at 20:49
  • 1
    @MATH000 Alright, then the example I just gave using default arguments and no macros behaves the same as the hypothetical examples you gave above. I don't understand what the problem is. – acwaters Jul 08 '16 at 20:50
  • @acwaters Thanks for the help! Your solution is actually solving the problem but maybe there is a solution that keeps the code structure like I have it now? – MATH000 Jul 08 '16 at 20:53
  • 3
    why do you want to keep the code structure? Having an overload that does something completely different is at best confusing – 463035818_is_not_an_ai Jul 08 '16 at 21:00
  • @MATH000 You could always write another function to do the dispatching: `int A (int id = 0) { if (id == 0) return defaultA(); else return paramaterizedA(id); }`, and then if you *really* wanted to you could change out `defaultA` and `paramaterizedA` for function overloads as you have in your example, e.g. `int A_()` and `int A_(int)` -- then the structure of the code would be as you have it now, with one extra function per function overload pair (although I really cannot discourage this enough). – acwaters Jul 08 '16 at 21:01
  • @MATH000 Better in what way? Obscuring the fact that the macro needs to call the function it's in makes things worse, not better. – David Schwartz Jul 08 '16 at 21:29

2 Answers2

1

I came up with this nasty thing, but it sort of works. It can call itself, with different parameters, but not different function with same name (overload). Also, it does not support default parameters.

#define BEGIN_FUNC(ret, name, ...) ret name(__VA_ARGS__) { ret(*SELF)(__VA_ARGS__) = name;
#define END_FUNC }

BEGIN_FUNC(int, factorial, int n)
    return n == 0 ? 1 : n * SELF(n - 1);
END_FUNC

int main()
{
    factorial(5);
}
Zereges
  • 5,139
  • 1
  • 25
  • 49
1

You can use the predefined variable __func__ to get the name of the current function. Does that help?

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Always Confused
  • 470
  • 4
  • 7
  • @HolyBlackCat thanks for the edit, I had not realized `__func__` is actually a constexpr variable. According to gcc's documentation though it would seem `__func__` is standard in C99 but not in C++. So it is still a compiler-specific solution is it not? – Always Confused Jul 09 '16 at 16:25
  • It's a part of C++, but surprisingly it's more or less new. It was added in C++11. – HolyBlackCat Jul 09 '16 at 16:56