1 #pragma once
2 
3 #ifdef PAJLADA_BOOST_ANY_SUPPORT
4 #include <boost/any.hpp>
5 #endif
6 
7 #include <map>
8 #include <vector>
9 
10 namespace pajlada {
11 
12 template <typename Type>
13 struct IsEqual {
14     static bool
getpajlada::IsEqual15     get(const Type &lhs, const Type &rhs)
16     {
17         return lhs == rhs;
18     }
19 };
20 
21 template <typename Type1, typename Type2>
22 struct IsEqual<std::pair<Type1, Type2>> {
23     static bool
getpajlada::IsEqual24     get(const std::pair<Type1, Type2> &lhs, const std::pair<Type1, Type2> &rhs)
25     {
26         return IsEqual<Type1>::get(lhs.first, rhs.first) &&
27                IsEqual<Type2>::get(lhs.second, rhs.second);
28     }
29 };
30 
31 #ifdef PAJLADA_BOOST_ANY_SUPPORT
32 template <>
33 struct IsEqual<boost::any> {
34     static bool
getpajlada::IsEqual35     get(const boost::any &lhs, const boost::any &rhs)
36     {
37         // two boost::any cannot be safely compared to each other, so we only consider them equal if both are empty
38         return (lhs.empty() && rhs.empty());
39     }
40 };
41 #endif
42 
43 template <typename KeyType, typename ValueType>
44 struct IsEqual<std::map<KeyType, ValueType>> {
45     static bool
getpajlada::IsEqual46     get(const std::map<KeyType, ValueType> &lhs,
47         const std::map<KeyType, ValueType> &rhs)
48     {
49         if (lhs.size() != rhs.size()) {
50             return false;
51         }
52 
53         return std::equal(lhs.begin(), lhs.end(), rhs.begin());
54     }
55 };
56 
57 #ifdef PAJLADA_BOOST_ANY_SUPPORT
58 template <typename KeyType>
59 struct IsEqual<std::map<KeyType, boost::any>> {
60     static bool
getpajlada::IsEqual61     get(const std::map<KeyType, boost::any> &lhs,
62         const std::map<KeyType, boost::any> &rhs)
63     {
64         if (lhs.size() != rhs.size()) {
65             return false;
66         }
67 
68         for (const auto &p : lhs) {
69             auto rit = rhs.find(p.first);
70 
71             if (rit == rhs.end()) {
72                 return false;
73             }
74 
75             if (!IsEqual<boost::any>::get(p.second, rit->second)) {
76                 return false;
77             }
78         }
79 
80         return true;
81     }
82 };
83 #endif
84 
85 template <typename ValueType>
86 struct IsEqual<std::vector<ValueType>> {
87     static bool
getpajlada::IsEqual88     get(const std::vector<ValueType> &lhs, const std::vector<ValueType> &rhs)
89     {
90         if (lhs.size() != rhs.size()) {
91             return false;
92         }
93 
94         return std::equal(lhs.begin(), lhs.end(), rhs.begin());
95     }
96 };
97 
98 #ifdef PAJLADA_BOOST_ANY_SUPPORT
99 template <>
100 struct IsEqual<std::vector<boost::any>> {
101     static bool
getpajlada::IsEqual102     get(const std::vector<boost::any> &lhs, const std::vector<boost::any> &rhs)
103     {
104         if (lhs.size() != rhs.size()) {
105             return false;
106         }
107 
108         auto lit = lhs.begin();
109         auto rit = rhs.begin();
110 
111         for (; lit != lhs.begin(); ++lit, ++rit) {
112             if (rit == rhs.end()) {
113                 return false;
114             }
115 
116             if (!IsEqual<boost::any>::get(*lit, *rit)) {
117                 return false;
118             }
119         }
120 
121         return true;
122     }
123 };
124 #endif
125 
126 }  // namespace pajlada
127