I know it is possible to write something like so:
struct Impl {
static bool f(int);
};
template<class Impl> struct Helper {
static constexpr auto f = Impl::f;
};
But is there any way to avoid copy paste of function parameters and return values in such case:
struct Impl {
static bool f(int);
};
struct Helper {
static const auto f = bind(*Impl::f, not_really_pimpl);
static Impl *not_really_pimpl;
};
I don't expect it to work (and it doesn't) but is there any sensible way to avoid repeating f() parameters and return value in such wrapper?
EDIT: Hundreds of stupid tests do Helper::f(). Now someone wanted to mock Helper. Helper is just a namespace of static functions which by chance appeared to be a class. Yes, I know that static functions do not allow mocking and blablabla, but they just want it.
I don't want to change a lot of code for just mocking. Also some amount of tests which would have to be rewritten if choosing between Helper : Impl and Helper : MockImpl is to be done at compile time for all of them, because they do use original Helper::f().
Also changing all this places where Helper::f() is called to some other syntax doesn't seem to be a good idea. So I'm just following a hack: Google Mock unit testing static methods c++ with this only difference that I cannot switch Helper with a template parameter for everything in compile time. It is simpler to just add a static pointer to implementation and call it from static functions. Then it is mockable/unmockable at runtime. It just adds even more copy-pasting than mocks itself.
I was thinking there exist a sensible (not too many code to make it make sense comparing to repeating) to somehow base this parameters on templates but as I'm switching pointer in runtime I think it's not possible? So I would have to write
struct Helper {
static bool f(int) { not_really_pimpl->f(); }
static NotReallyPimpl real_impl;
static Impl* not_really_pimpl = &real_pimpl; // pseudocode
};
and also
struct NotReallyPimpl {
virtual bool f(int) { /* here is the job done */ }
};
and also
struct MockNotReallyPimpl : public NotReallyPimpl {
MOCK_METHOD1(f, bool(int));
};
Then old test code will use Helper::f(). Some new test code which wishes to mock Helper would do:
MockNotReallyPimpl mock;
Helper::not_really_pimpl = &mock;
EXPECT_CALL(mock, f, blablabla).WillBlabla(WithBlablabla())).
Helper::not_really_pimpl = Helper::real_impl; // in TearDown