00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __SIDE_EFFECT_STRATEGY_HH
00018 # define __SIDE_EFFECT_STRATEGY_HH
00019
00020 # include "../strategies.hh"
00021 # include <memory>
00022
00023 namespace aurelia {
00024
00031 template <typename Model>
00032 struct side_effect_strategy_concept {
00033 typedef typename Model::strat strat;
00034 typedef typename Model::input input;
00035 typedef typename Model::output output;
00037 #ifdef DOC_GEN
00038 output operator()(strat&, input);
00039 #else
00040 static_assert(std::is_same<decltype(std::declval<strat&>()
00041 (std::declval<input>())),
00042 output>::value,
00043 "operator() does not return the right type");
00044
00045 typedef void check;
00046 #endif
00047 };
00056 template <typename S, typename I>
00057 struct default_side_effect_strategy_model {
00058 typedef S strat;
00059 typedef I input;
00060 typedef decltype(std::declval<strat&>()(std::declval<input>())) output;
00061 };
00064 template <typename S, typename I>
00065 struct side_effect_strategy_model {
00066 typedef default_side_effect_strategy_model<S, I> model;
00067 };
00068
00072 template <typename Kernel>
00073 struct side_effect_strategy {
00074 private:
00075 std::shared_ptr<Kernel> k;
00076
00077 public:
00078 side_effect_strategy(const Kernel& k): k(new Kernel(k)) {}
00079 side_effect_strategy(const side_effect_strategy& other): k(other.k) {}
00080
00081 void swap(side_effect_strategy& other) {
00082 std::swap(k, other.k);
00083 }
00084
00085 side_effect_strategy& operator=(side_effect_strategy other) {
00086 this->swap(other);
00087 return *this;
00088 }
00089
00090 template <typename T,
00091 typename M =
00092 typename side_effect_strategy_model<Kernel, T>::model>
00093 typename M::output
00094 operator()(const T& t) const {
00095 typedef typename side_effect_strategy_concept<M>::check requires;
00096 return (*k)(t);
00097 }
00098
00099 const Kernel* operator->() const {
00100 return k.operator->();
00101 }
00102
00103 Kernel* operator->() {
00104 return k.operator->();
00105 }
00106
00107 Kernel& operator*() {
00108 return *k;
00109 }
00110
00111 const Kernel& operator*() const {
00112 return *k;
00113 }
00114 };
00115
00125 template <typename Kernel>
00126 side_effect_strategy<Kernel> side_effect(const Kernel& k) {
00127 return side_effect_strategy<Kernel>(k);
00128 }
00129
00130 }
00131
00132 #endif