-1

I am trying to use a macro which takes advantage of the preprocessor __FUNCTION__ to switch to calling a function by the same name as the macro caller, but in a different class.

(This is a simple mocking framework implemented without inheritance.)

#define FAKE(def) enabled(__FUNCTION__) ? def : _foo.__FUNCTION__()

The usage is like this:

#include <iostream>

struct Foo {
    int bar() { return 42; }
};

#define FAKE(def) enabled() ? def : _foo.__FUNCTION__()

struct Fake {
    Fake(Foo& foo) : _foo(foo) {}
    Foo& _foo;
    bool enabled(const char*) const { return true; } // for example
    int bar() {
        return FAKE(1337); // doesn't work
    }
};

which gives the error:

error: '__FUNCTION__' cannot be used as a function

This seems to be due to the fact that __FUNCTION__ is not a macro but a string literal.

Is there an easy-ish workaround? I would prefer not to cache some mapping of strings to function pointers or something. I know C++ doesn't support reflection, but I was hoping the preprocessor could sort this out somehow.

Live example

tomocafe
  • 1,425
  • 4
  • 20
  • 35
  • Another duplicate [Unquote \_\_FUNCTION__ macro in C++](https://stackoverflow.com/questions/36352289/unquote-function-macro-in-c) with "not possible" comments. – dxiv Jan 22 '21 at 01:20
  • `#define FAKE(R, FUNC, DEFAULT) R FUNC() { return enabled(__FUNCTION__)?DEFAULT:_foo.FUNC(); }` should work. Might need `FUNCEX(R, FUNC, MODIFIERS, DEFAULT)` or the like. – Yakk - Adam Nevraumont Jan 22 '21 at 04:29

1 Answers1

2

Is there an easy-ish workaround?

No.

I would prefer not to cache some mapping of strings to function pointers or something

If you want runtime dispatch, then this is the way to go.

I know C++ doesn't support reflection, but I was hoping the preprocessor could sort this out somehow.

And because C++ does not support reflection, no language feature will "sort this out". The language itself does not support finding a function by it's string representation. Preprocessor is a (simple) string replacement tool. __FUNCTION__ is not a string literal - __FUNCTION__ works like as-if a static const char * variable would be defined in the function. Do not use __FUNCTION__, it's an extension, use __func__. In C++20 see source_location.

But there is no need to use reflection. In C++, use SFINAE. In C++17, there's if constexpr. In C++20, there are concepts. For example see this answer to Templated check for the existence of a class member function?.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111