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