00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef BLACK_BOX_EQUAL_HH
00018 # define BLACK_BOX_EQUAL_HH
00019
00020 # include <functional>
00021 # include "../dataset/dataset.hh"
00022 # include "../concept/concepts.hh"
00023 # include "../wrappers/function_wrappers.hh"
00024
00025 namespace catsfoot {
00026
00027 namespace details {
00028 template <typename T, typename Op>
00029 struct try_all_compare;
00030
00031 template <typename T, typename Ret, typename... Args>
00032 struct try_all_compare<T, std::function<Ret(Args...)> > {
00033 template <typename Generator, typename... OtherArgs>
00034 static bool doit(Generator& g,
00035 const selector<const T&>&,
00036 const std::function<Ret(Args...)>& f,
00037 const T& a, const T& b,
00038 const std::tuple<OtherArgs, OtherArgs>&... args...) {
00039 return doit(g, f, a, b, args..., std::tuple<const T&, const T&>(a, b));
00040 }
00041
00042 template <typename Generator, typename U, typename... OtherArgs>
00043 static bool doit(Generator& g,
00044 const selector<U>&,
00045 const std::function<Ret(Args...)>& f,
00046 const T& a, const T& b,
00047 const std::tuple<OtherArgs, OtherArgs>&... args...) {
00048 auto gen = g.get(selector<U>{});
00049 for (auto i = gen.begin();
00050 i != gen.end(); ++i) {
00051 if (!doit(g, f, a, b, args..., std::tuple<U, U>(*i, *i)))
00052 return false;
00053 }
00054 return true;
00055 }
00056
00057 template <typename Generator, typename... OtherArgs>
00058 static bool doit(Generator& g,
00059 const std::function<Ret(Args...)>& f,
00060 const T& a, const T& b,
00061 const std::tuple<OtherArgs, OtherArgs>&... args...) {
00062 typedef typename std::
00063 tuple_element<sizeof...(OtherArgs), std::tuple<Args...> >::type type;
00064
00065 return doit(g, selector<type>(), f, a, b, args...);
00066 }
00067
00069 template <typename Generator>
00070 static bool doit(Generator&,
00071 const std::function<Ret(Args...)>& f,
00072 const T&, const T&, const std::tuple<Args, Args>&...
00073 args...) {
00074 return f(std::get<0>(args)...) ==
00075 f(std::get<1>(args)...);
00076 }
00077
00078 };
00079 }
00080
00081 namespace details {
00083 template <typename Generator, typename T, typename... Ops>
00084 struct compare;
00085
00087 template <typename Generator, typename T>
00088 struct compare<Generator, T> {
00089 compare() = default;
00090
00091 bool operator()(Generator&, const T&, const T&) const {
00092 return true;
00093 }
00094 };
00095
00097 template <typename Generator, typename T, typename Op, typename... Ops>
00098 struct compare<Generator, T, Op, Ops...>:
00099 public compare<Generator, T, Ops...> {
00100 private:
00101 typedef compare<Generator, T, Ops...> super;
00102 Op op;
00103 public:
00104 compare(Op&& op,
00105 Ops&&... ops...):
00106 compare<Generator, T, Ops...>(std::move(ops)...),
00107 op(std::move(op))
00108 {}
00109
00110 bool operator()(Generator &g, const T& a, const T& b) const {
00111 if (!this->super::operator()(g, a, b))
00112 return false;
00113 return details::try_all_compare<T, Op>::doit(g, op, a, b);
00114 }
00115 };
00116
00118 template <typename Generator, typename T, typename... Ops>
00119 struct compare_top: public compare<Generator, T, Ops...> {
00120 private:
00121 Generator g;
00122 public:
00123 compare_top(const Generator& g,
00124 Ops&&... ops...):
00125 compare<Generator, T, Ops...>(std::move(ops)...),
00126 g(g)
00127 {}
00128
00129 compare_top(Generator&& g,
00130 Ops&&... ops...):
00131 compare<Generator, T, Ops...>(std::move(ops)...),
00132 g(std::move(g))
00133 {}
00134
00135 bool operator()(const T& a, const T& b) const {
00136 return this->compare<Generator, T, Ops...>::operator()
00137 (*const_cast<Generator*>(&g), a, b);
00138 }
00139 };
00140
00141 }
00142
00146 template <typename T>
00147 struct build_comparer {
00148 template <typename Generator, typename... Functions,
00149 typename G = typename std::decay<Generator>::type>
00150 details::compare_top<G, T, typename wrapped<Functions>::type...>
00151 operator()(Generator g, Functions&&... functions...) const {
00152 return details::compare_top<G, T, typename wrapped<Functions>::type...>
00153 (std::forward<Generator>(g),
00154 wrap(std::forward<Functions>(functions))...);
00155 }
00156 };
00157 }
00158
00159 #endif