fork download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <experimental/optional>
  4.  
  5. template <class C>
  6. using opt = std::experimental::optional<C>;
  7.  
  8. auto nullopt = std::experimental::nullopt;
  9.  
  10. class Nothing {};
  11.  
  12. template <class T>
  13. class Maybe
  14. {
  15. opt<T> t;
  16. public:
  17. Maybe(const T& tt) : t(tt) {}
  18. Maybe(const Maybe& mt) : t(mt.t) {}
  19. Maybe(Nothing n) : t(nullopt) {}
  20. Maybe() : t(nullopt) {}
  21.  
  22. template<class M, class Q = T>
  23. typename std::enable_if<std::is_class<T>::value, Maybe<M>>::type
  24. fetch(M Q::*memptr)
  25. {
  26. if (t)
  27. return Maybe<M>((*t).*memptr);
  28. else
  29. return Maybe<M>(Nothing());
  30. }
  31.  
  32. template<class M, class Q = T>
  33. typename std::enable_if<std::is_class<T>::value, Maybe<M>>::type
  34. fetch(Maybe<M> Q::*memptr)
  35. {
  36. if (t)
  37. return Maybe<M>((*t).*memptr);
  38. else
  39. return Maybe<M>(Nothing());
  40. }
  41.  
  42. operator bool() const { return bool(t); }
  43. T& operator*() { return *t; }
  44. T* operator->() { return &*t; }
  45. const T& operator*() const { return *t; }
  46. const T* operator->() const { return &*t; }
  47.  
  48. };
  49.  
  50.  
  51. struct C
  52. {
  53. int d;
  54. };
  55.  
  56. struct B
  57. {
  58. Maybe<C> c;
  59. B(C c) : c(c) {}
  60. B() : c() {}
  61. };
  62.  
  63. struct A
  64. {
  65. Maybe<B> b;
  66. A(B b) : b(b) {}
  67. A() : b() {}
  68. };
  69.  
  70. void test(Maybe<A> a)
  71. {
  72. Maybe<int> d = a.fetch(&A::b).fetch(&B::c).fetch(&C::d);
  73. if (!d)
  74. std::cout << "empty\n";
  75. else
  76. std::cout << *d << "\n";
  77. };
  78.  
  79. int main()
  80. {
  81. Maybe<A> empty1{Nothing{}};
  82. Maybe<A> empty2{A()};
  83. Maybe<A> empty3{A(B())};
  84. Maybe<A> full (A(B(C{42})));
  85.  
  86. test(empty1);
  87. test(empty2);
  88. test(empty3);
  89. test(full);
  90. }
  91.  
Success #stdin #stdout 0s 4492KB
stdin
Standard input is empty
stdout
empty
empty
empty
42