#include int foo1(int i) { return i * 2; } float foo2(int i, int j) { return i / float(j); } int foo3(int i, char c) { return i * c; } namespace my { int foo1(int i) { return i * 8; } float foo2(int i, int j) { return j / float(i); } int foo3(int i, char c) { return i - c; } } // namespace my namespace dyn { template struct dyn_call_impl; template struct dyn_call_impl { constexpr static auto value = +[](Args... args) -> R { // std::cout << "Checking predicate... "; if (Pred()) { Self = B; // std::cout << "Using replacement.\n"; } else { Self = A; // std::cout << "Using original.\n"; } return Self(std::forward(args)...); }; }; template decltype(A) dyn_call() { return dyn_call_impl::value; } #define DYN(Name, A, B, Pred) \ inline decltype(A)* Name = ::dyn::dyn_call() #define DYN_PRED(Name, A, B) \ inline bool DECIDE_##Name(); \ inline decltype(A)* Name = ::dyn::dyn_call(); \ inline bool DECIDE_##Name() bool yes() { return true; } bool no() { return false; } DYN(foo1, ::foo1, my::foo1, no); DYN(foo2, ::foo2, my::foo2, yes); DYN_PRED(foo3, ::foo3, my::foo3) { std::cout << "Use new? y/n\n> "; return std::cin.get() == 'y'; } } // namespace dyn int dyn_main(int, char**) { std::cout << dyn::foo1(100) << '\n' << dyn::foo2(49, 3) << '\n'; // auto c = std::cin.peek(); std::cout << dyn::foo3(127, ' ') << '\n'; auto c = std::cin.unget().get(); std::cout << "expected:\n" << foo1(100) << '\n' << my::foo2(49, 3) << '\n' << (c == 'y' ? my::foo3 : foo3)(127, ' ') << '\n'; std::cout << "Did not expect:\n" << my::foo1(100) << '\n' << foo2(49, 3) << '\n' << (c != 'y' ? my::foo3 : foo3)(127, ' ') << '\n'; std::cout << "Only checks once:\n"; std::cout << dyn::foo1(100) << '\n' << dyn::foo2(49, 3) << '\n' << dyn::foo3(127, ' ') << '\n'; return 0; }