1 
2 #include <algorithm>
3 #include <cstdint>
4 #include <cstdlib>
5 #include <iostream>
6 #include <sstream>
7 #include <string>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
11 
12 #include <mapbox/variant.hpp>
13 #include <mapbox/variant_io.hpp>
14 
15 using namespace mapbox;
16 
17 namespace test {
18 
19 template <typename T>
20 struct string_to_number
21 {
22 };
23 
24 template <>
25 struct string_to_number<double>
26 {
operator ()test::string_to_number27     double operator()(std::string const& str) const
28     {
29         return std::stod(str);
30     }
31 };
32 
33 template <>
34 struct string_to_number<std::int64_t>
35 {
operator ()test::string_to_number36     std::int64_t operator()(std::string const& str) const
37     {
38         return std::stoll(str);
39     }
40 };
41 
42 template <>
43 struct string_to_number<std::uint64_t>
44 {
operator ()test::string_to_number45     std::uint64_t operator()(std::string const& str) const
46     {
47         return std::stoull(str);
48     }
49 };
50 
51 template <>
52 struct string_to_number<bool>
53 {
operator ()test::string_to_number54     bool operator()(std::string const& str) const
55     {
56         bool result;
57         std::istringstream(str) >> std::boolalpha >> result;
58         return result;
59     }
60 };
61 
62 struct javascript_equal_visitor
63 {
64     template <typename T>
operator ()test::javascript_equal_visitor65     bool operator()(T lhs, T rhs) const
66     {
67         return lhs == rhs;
68     }
69 
70     template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
operator ()test::javascript_equal_visitor71     bool operator()(T lhs, std::string const& rhs) const
72     {
73         return lhs == string_to_number<T>()(rhs);
74     }
75 
76     template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
operator ()test::javascript_equal_visitor77     bool operator()(std::string const& lhs, T rhs) const
78     {
79         return string_to_number<T>()(lhs) == rhs;
80     }
81 
82     template <typename T0, typename T1>
operator ()test::javascript_equal_visitor83     bool operator()(T0 lhs, T1 rhs) const
84     {
85         return lhs == static_cast<T0>(rhs);
86     }
87 };
88 
89 template <typename T>
90 struct javascript_equal
91 {
javascript_equaltest::javascript_equal92     javascript_equal(T const& lhs)
93         : lhs_(lhs) {}
94 
operator ()test::javascript_equal95     bool operator()(T const& rhs) const
96     {
97         return util::apply_visitor(test::javascript_equal_visitor(), lhs_, rhs);
98     }
99     T const& lhs_;
100 };
101 
102 } // namespace test
103 
main()104 int main()
105 {
106     typedef util::variant<bool, std::int64_t, std::uint64_t, double, std::string> variant_type;
107     variant_type v0(3.14159);
108     variant_type v1(std::string("3.14159"));
109     variant_type v2(std::uint64_t(1));
110 
111     std::cerr << v0 << " == " << v1 << " -> "
112               << std::boolalpha << util::apply_visitor(test::javascript_equal_visitor(), v0, v1) << std::endl;
113 
114     std::vector<variant_type> vec;
115 
116     vec.emplace_back(std::string("1"));
117     vec.push_back(variant_type(std::uint64_t(2)));
118     vec.push_back(variant_type(std::uint64_t(3)));
119     vec.push_back(std::string("3.14159"));
120     vec.emplace_back(3.14159);
121 
122     //auto itr = std::find_if(vec.begin(), vec.end(), [&v0](variant_type const& val) {
123     //        return util::apply_visitor(test::javascript_equal_visitor(), v0, val);
124     //    });
125 
126     auto itr = std::find_if(vec.begin(), vec.end(), test::javascript_equal<variant_type>(v2));
127 
128     if (itr != std::end(vec))
129     {
130         std::cout << "found " << *itr << std::endl;
131     }
132     else
133     {
134         std::cout << "can't find " << v2 << '\n';
135     }
136 
137     return EXIT_SUCCESS;
138 }
139