0

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
xor256
  • 197
  • 9
  • 1
    `template struct Helper : Impl {}` ? – Jarod42 Dec 07 '18 at 18:38
  • Won't help. Helper functions need to remain static. And a pointer has to be interchengeable in runtime (at least this is the easiest things to do, when code that uses Helper::f() cannot be touched to add something like using Helper = HelperT, it's just too many of it. – xor256 Dec 07 '18 at 18:45
  • Also some code wants an original Helper and some a changed one. It's one big mess to just switch it in compile time :( – xor256 Dec 07 '18 at 18:52
  • 2
    i dont get what the `bind` is supposed to be good for, `f` is a static function so you dont need that `not_really_pimpl` to call it – 463035818_is_not_an_ai Dec 07 '18 at 18:52
  • Show usage, as I don't see problem with my proposal [Demo](https://ideone.com/BHklTm). – Jarod42 Dec 07 '18 at 18:55
  • I don't get what is really asked here? Where should be the retval and parms moved away/not repeated...? – Klaus Dec 07 '18 at 19:11
  • @Klaus added an EDIT – xor256 Dec 07 '18 at 19:13

0 Answers0