fork download
  1. #include <iostream>
  2.  
  3.  
  4. template<typename T, typename LogFunc>
  5. class Foo {
  6. public:
  7. Foo(const T& t, LogFunc fn) : t_(t), lfn_(fn) {}
  8.  
  9. template<typename LFN>
  10. Foo& operator+=(const Foo<T, LFN>& other) {
  11. lfn_(t_, other());
  12. t_ += other();
  13. return *this;
  14. }
  15. T operator()() const { return t_; }
  16.  
  17. private:
  18. T t_;
  19. LogFunc lfn_;
  20. };
  21.  
  22. template<typename T, typename LogFunc>
  23. std::ostream& operator<<(std::ostream& o, const Foo<T, LogFunc>& f) {
  24. return o << f();
  25. }
  26.  
  27. // It's actually amazing that this works, and I presume that it works because it
  28. // is only used in an inline function, from which it can be resolved at
  29. // compile-time.
  30. struct Noop {
  31. template<typename...A>
  32. void operator()(A...) { };
  33. };
  34.  
  35. template<typename T, typename LogFunc=Noop>
  36. Foo<T, LogFunc> make_foo(const T& t, LogFunc func=LogFunc()) {
  37. return Foo<T, LogFunc>(t, func);
  38. }
  39.  
  40. template<typename T>
  41. void log(std::ostream& o, const T& a, const T& b) {
  42. o << "a: " << a << " b: " << b << std::endl;
  43. }
  44.  
  45. int main(int argc, char**argv) {
  46. auto f1 = make_foo(3.141592653);
  47. auto f2 = make_foo(2.5, [&](double a, double b) { log(std::cout, a, b); });
  48. f1 += f2;
  49. f2 += f1;
  50. std::cout << "f1: " << f1 << " f2: " << f2 << std::endl;
  51. return 0;
  52. }
Success #stdin #stdout 0s 2884KB
stdin
Standard input is empty
stdout
a: 2.5 b: 5.64159
f1: 5.64159 f2: 8.14159