move external dependence mapbox/variant into third_party directory
This commit is contained in:
+204
@@ -0,0 +1,204 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include "variant.hpp"
|
||||
|
||||
#define TEXT "Testing various variant implementations with a longish string ........................................."
|
||||
//#define BOOST_VARIANT_MINIMIZE_SIZE
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename V>
|
||||
struct Holder
|
||||
{
|
||||
typedef V value_type;
|
||||
std::vector<value_type> data;
|
||||
|
||||
template <typename T>
|
||||
void append_move(T && obj)
|
||||
{
|
||||
data.emplace_back(std::forward<T>(obj));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void append(T const& obj)
|
||||
{
|
||||
data.push_back(obj);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
struct print : util::static_visitor<>
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
std::cerr << val << ":" << typeid(T).name() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename V>
|
||||
struct dummy : boost::static_visitor<>
|
||||
{
|
||||
dummy(V & v)
|
||||
: v_(v) {}
|
||||
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
v_ = val;
|
||||
}
|
||||
V & v_;
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
struct dummy2 : util::static_visitor<>
|
||||
{
|
||||
dummy2(V & v)
|
||||
: v_(v) {}
|
||||
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
v_.template set<T>(val);
|
||||
}
|
||||
V & v_;
|
||||
};
|
||||
|
||||
void run_boost_test(std::size_t runs)
|
||||
{
|
||||
test::Holder<boost::variant<int, double, std::string>> h;
|
||||
h.data.reserve(runs);
|
||||
for (std::size_t i=0; i< runs; ++i)
|
||||
{
|
||||
h.append_move(std::string(TEXT));
|
||||
h.append_move(123);
|
||||
h.append_move(3.14159);
|
||||
}
|
||||
|
||||
boost::variant<int, double, std::string> v;
|
||||
for (auto const& v2 : h.data)
|
||||
{
|
||||
dummy<boost::variant<int, double, std::string>> d(v);
|
||||
boost::apply_visitor(d, v2);
|
||||
}
|
||||
}
|
||||
|
||||
void run_variant_test(std::size_t runs)
|
||||
{
|
||||
test::Holder<util::variant<int, double, std::string>> h;
|
||||
h.data.reserve(runs);
|
||||
for (std::size_t i=0; i< runs; ++i)
|
||||
{
|
||||
h.append_move(std::string(TEXT));
|
||||
h.append_move(123);
|
||||
h.append_move(3.14159);
|
||||
}
|
||||
|
||||
util::variant<int, double, std::string> v;
|
||||
for (auto const& v2 : h.data)
|
||||
{
|
||||
dummy2<util::variant<int, double, std::string>> d(v);
|
||||
util::apply_visitor (d, v2);
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
if (argc!=2)
|
||||
{
|
||||
std::cerr << "Usage:" << argv[0] << " <num-runs>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef SINGLE_THREADED
|
||||
const std::size_t THREADS = 4;
|
||||
#endif
|
||||
const std::size_t NUM_RUNS = static_cast<std::size_t>(std::stol(argv[1]));
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
{
|
||||
std::cerr << "custom variant: ";
|
||||
boost::timer::auto_cpu_timer t;
|
||||
run_variant_test(NUM_RUNS);
|
||||
}
|
||||
{
|
||||
std::cerr << "boost variant: ";
|
||||
boost::timer::auto_cpu_timer t;
|
||||
run_boost_test(NUM_RUNS);
|
||||
}
|
||||
{
|
||||
std::cerr << "custom variant: ";
|
||||
boost::timer::auto_cpu_timer t;
|
||||
run_variant_test(NUM_RUNS);
|
||||
}
|
||||
{
|
||||
std::cerr << "boost variant: ";
|
||||
boost::timer::auto_cpu_timer t;
|
||||
run_boost_test(NUM_RUNS);
|
||||
}
|
||||
#else
|
||||
{
|
||||
typedef std::vector<std::unique_ptr<std::thread>> thread_group;
|
||||
typedef thread_group::value_type value_type;
|
||||
thread_group tg;
|
||||
std::cerr << "custom variant: ";
|
||||
boost::timer::auto_cpu_timer timer;
|
||||
for (std::size_t i=0; i<THREADS; ++i)
|
||||
{
|
||||
tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
|
||||
}
|
||||
std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
|
||||
}
|
||||
|
||||
{
|
||||
typedef std::vector<std::unique_ptr<std::thread>> thread_group;
|
||||
typedef thread_group::value_type value_type;
|
||||
thread_group tg;
|
||||
std::cerr << "boost variant: ";
|
||||
boost::timer::auto_cpu_timer timer;
|
||||
for (std::size_t i=0; i<THREADS; ++i)
|
||||
{
|
||||
tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
|
||||
}
|
||||
std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
|
||||
}
|
||||
|
||||
{
|
||||
typedef std::vector<std::unique_ptr<std::thread>> thread_group;
|
||||
typedef thread_group::value_type value_type;
|
||||
thread_group tg;
|
||||
std::cerr << "custom variant: ";
|
||||
boost::timer::auto_cpu_timer timer;
|
||||
for (std::size_t i=0; i<THREADS; ++i)
|
||||
{
|
||||
tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
|
||||
}
|
||||
std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
|
||||
}
|
||||
|
||||
{
|
||||
typedef std::vector<std::unique_ptr<std::thread>> thread_group;
|
||||
typedef thread_group::value_type value_type;
|
||||
thread_group tg;
|
||||
std::cerr << "boost variant: ";
|
||||
boost::timer::auto_cpu_timer timer;
|
||||
for (std::size_t i=0; i<THREADS; ++i)
|
||||
{
|
||||
tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
|
||||
}
|
||||
std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include "variant.hpp"
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename T>
|
||||
struct string_to_number {};
|
||||
|
||||
template <>
|
||||
struct string_to_number<double>
|
||||
{
|
||||
double operator() (std::string const& str) const
|
||||
{
|
||||
return std::stod(str);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct string_to_number<std::int64_t>
|
||||
{
|
||||
std::int64_t operator() (std::string const& str) const
|
||||
{
|
||||
return std::stoll(str);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct string_to_number<std::uint64_t>
|
||||
{
|
||||
std::uint64_t operator() (std::string const& str) const
|
||||
{
|
||||
return std::stoull(str);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct string_to_number<bool>
|
||||
{
|
||||
bool operator() (std::string const& str) const
|
||||
{
|
||||
bool result;
|
||||
std::istringstream(str) >> std::boolalpha >> result;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct javascript_equal_visitor : util::static_visitor<bool>
|
||||
{
|
||||
template <typename T>
|
||||
bool operator() (T lhs, T rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
bool operator() (T lhs, std::string const& rhs) const
|
||||
{
|
||||
return lhs == string_to_number<T>()(rhs);
|
||||
}
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
bool operator() (std::string const& lhs, T rhs) const
|
||||
{
|
||||
return string_to_number<T>()(lhs) == rhs;
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
bool operator() (T0 lhs, T1 rhs) const
|
||||
{
|
||||
return lhs == static_cast<T0>(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct javascript_equal
|
||||
{
|
||||
javascript_equal(T const& lhs)
|
||||
: lhs_(lhs) {}
|
||||
|
||||
bool operator() (T const& rhs) const
|
||||
{
|
||||
return util::apply_visitor(test::javascript_equal_visitor(), lhs_, rhs);
|
||||
}
|
||||
T const& lhs_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
int main (/*int argc, char** argv*/)
|
||||
{
|
||||
typedef util::variant<bool, std::int64_t, std::uint64_t, double, std::string> variant_type;
|
||||
variant_type v0(3.14159);
|
||||
variant_type v1(std::string("3.14159"));
|
||||
variant_type v2(std::uint64_t(1));
|
||||
|
||||
std::cerr << v0 << " == " << v1 << " -> "
|
||||
<< std::boolalpha << util::apply_visitor(test::javascript_equal_visitor(), v0, v1) << std::endl;
|
||||
|
||||
|
||||
std::vector<variant_type> vec;
|
||||
|
||||
vec.emplace_back(std::string("1"));
|
||||
vec.push_back(variant_type(std::uint64_t(2)));
|
||||
vec.push_back(variant_type(std::uint64_t(3)));
|
||||
vec.push_back(std::string("3.14159"));
|
||||
vec.emplace_back(3.14159);
|
||||
|
||||
//auto itr = std::find_if(vec.begin(), vec.end(), [&v0](variant_type const& val) {
|
||||
// return util::apply_visitor(test::javascript_equal_visitor(), v0, val);
|
||||
// });
|
||||
|
||||
auto itr = std::find_if(vec.begin(), vec.end(), test::javascript_equal<variant_type>(v2));
|
||||
|
||||
if (itr != std::end(vec))
|
||||
{
|
||||
std::cout << "found " << *itr << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "can't find " << v2 << '\n';
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <boost/variant.hpp>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
struct check : boost::static_visitor<>
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
if (val != 0) throw std::runtime_error("invalid");
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
typedef boost::variant<bool, int, double> variant_type;
|
||||
variant_type v(0);
|
||||
boost::apply_visitor(check(), v);
|
||||
return 0;
|
||||
}
|
||||
Vendored
+8683
File diff suppressed because it is too large
Load Diff
+82
@@ -0,0 +1,82 @@
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "optional.hpp"
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
struct dummy {
|
||||
dummy(int _m_1, int _m_2) : m_1(_m_1), m_2(_m_2) {}
|
||||
int m_1;
|
||||
int m_2;
|
||||
|
||||
};
|
||||
|
||||
int main (int argc, char* const argv[])
|
||||
{
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST_CASE( "optional can be instantiated with a POD type", "[optiona]" ) {
|
||||
mapbox::util::optional<double> dbl_opt;
|
||||
|
||||
REQUIRE(!dbl_opt);
|
||||
dbl_opt = 3.1415;
|
||||
REQUIRE(dbl_opt);
|
||||
|
||||
REQUIRE(dbl_opt.get() == 3.1415);
|
||||
REQUIRE(*dbl_opt == 3.1415);
|
||||
}
|
||||
|
||||
TEST_CASE( "copy c'tor", "[optiona]" ) {
|
||||
mapbox::util::optional<double> dbl_opt;
|
||||
|
||||
REQUIRE(!dbl_opt);
|
||||
dbl_opt = 3.1415;
|
||||
REQUIRE(dbl_opt);
|
||||
|
||||
mapbox::util::optional<double> other = dbl_opt;
|
||||
|
||||
REQUIRE(other.get() == 3.1415);
|
||||
REQUIRE(*other == 3.1415);
|
||||
}
|
||||
|
||||
TEST_CASE( "const operator*, const get()", "[optiona]" ) {
|
||||
mapbox::util::optional<double> dbl_opt = 3.1415;
|
||||
|
||||
REQUIRE(dbl_opt);
|
||||
|
||||
const double pi1 = dbl_opt.get();
|
||||
const double pi2 = *dbl_opt;
|
||||
|
||||
REQUIRE(pi1 == 3.1415);
|
||||
REQUIRE(pi2 == 3.1415);
|
||||
}
|
||||
|
||||
TEST_CASE( "emplace initialization, reset", "[optional]" ) {
|
||||
mapbox::util::optional<dummy> dummy_opt;
|
||||
REQUIRE(!dummy_opt);
|
||||
|
||||
// rvalues, baby!
|
||||
dummy_opt.emplace(1, 2);
|
||||
REQUIRE(dummy_opt);
|
||||
REQUIRE(dummy_opt.get().m_1 == 1);
|
||||
REQUIRE((*dummy_opt).m_2 == 2);
|
||||
|
||||
dummy_opt.reset();
|
||||
REQUIRE(!dummy_opt);
|
||||
}
|
||||
|
||||
TEST_CASE( "assignment", "[optional]") {
|
||||
mapbox::util::optional<int> a;
|
||||
mapbox::util::optional<int> b;
|
||||
|
||||
a = 1; b = 3;
|
||||
REQUIRE(a.get() == 1);
|
||||
REQUIRE(b.get() == 3);
|
||||
b = a;
|
||||
REQUIRE(a.get() == b.get());
|
||||
REQUIRE(b.get() == 1);
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include "variant.hpp"
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
namespace test {
|
||||
|
||||
struct add;
|
||||
struct sub;
|
||||
template <typename OpTag> struct binary_op;
|
||||
|
||||
typedef util::variant<int ,
|
||||
util::recursive_wrapper<binary_op<add>>,
|
||||
util::recursive_wrapper<binary_op<sub>>
|
||||
> expression;
|
||||
|
||||
template <typename Op>
|
||||
struct binary_op
|
||||
{
|
||||
expression left; // variant instantiated here...
|
||||
expression right;
|
||||
|
||||
binary_op(expression && lhs, expression && rhs)
|
||||
: left(std::move(lhs)), right(std::move(rhs))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct print : util::static_visitor<void>
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
std::cerr << val << ":" << typeid(T).name() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct test : util::static_visitor<std::string>
|
||||
{
|
||||
template <typename T>
|
||||
std::string operator() (T const& obj) const
|
||||
{
|
||||
return std::string("TYPE_ID=") + typeid(obj).name();
|
||||
}
|
||||
};
|
||||
|
||||
struct calculator : public util::static_visitor<int>
|
||||
{
|
||||
public:
|
||||
|
||||
int operator()(int value) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
int operator()(binary_op<add> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary.left)
|
||||
+ util::apply_visitor(calculator(), binary.right);
|
||||
}
|
||||
|
||||
int operator()(binary_op<sub> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary.left)
|
||||
- util::apply_visitor(calculator(), binary.right);
|
||||
}
|
||||
};
|
||||
|
||||
struct to_string : public util::static_visitor<std::string>
|
||||
{
|
||||
public:
|
||||
|
||||
std::string operator()(int value) const
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::string operator()(binary_op<add> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(to_string(), binary.left) + std::string("+")
|
||||
+ util::apply_visitor(to_string(), binary.right);
|
||||
}
|
||||
|
||||
std::string operator()(binary_op<sub> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(to_string(), binary.left) + std::string("-")
|
||||
+ util::apply_visitor(to_string(), binary.right);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage" << argv[0] << " <num-iter>" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const std::size_t NUM_ITER = static_cast<std::size_t>(std::stol(argv[1]));
|
||||
|
||||
test::expression result(
|
||||
test::binary_op<test::sub>(
|
||||
test::binary_op<test::add>(2, 3), 4));
|
||||
|
||||
std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl;
|
||||
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
int total = 0;
|
||||
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
||||
{
|
||||
total += util::apply_visitor(test::calculator(), result);
|
||||
}
|
||||
std::cerr << "total=" << total << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include "variant.hpp"
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
namespace test {
|
||||
|
||||
struct add;
|
||||
struct sub;
|
||||
template <typename OpTag> struct binary_op;
|
||||
|
||||
typedef util::variant<int ,
|
||||
std::unique_ptr<binary_op<add>>,
|
||||
std::unique_ptr<binary_op<sub>>
|
||||
> expression;
|
||||
|
||||
template <typename Op>
|
||||
struct binary_op
|
||||
{
|
||||
expression left; // variant instantiated here...
|
||||
expression right;
|
||||
|
||||
binary_op(expression && lhs, expression && rhs)
|
||||
: left(std::move(lhs)), right(std::move(rhs)) {}
|
||||
};
|
||||
|
||||
struct print : util::static_visitor<void>
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
std::cerr << val << ":" << typeid(T).name() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct test : util::static_visitor<std::string>
|
||||
{
|
||||
template <typename T>
|
||||
std::string operator() (T const& obj) const
|
||||
{
|
||||
return std::string("TYPE_ID=") + typeid(obj).name();
|
||||
}
|
||||
};
|
||||
|
||||
struct calculator : public util::static_visitor<int>
|
||||
{
|
||||
public:
|
||||
|
||||
int operator()(int value) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
int operator()(std::unique_ptr<binary_op<add>> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary->left)
|
||||
+ util::apply_visitor(calculator(), binary->right);
|
||||
}
|
||||
|
||||
int operator()(std::unique_ptr<binary_op<sub>> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary->left)
|
||||
- util::apply_visitor(calculator(), binary->right);
|
||||
}
|
||||
};
|
||||
|
||||
struct to_string : public util::static_visitor<std::string>
|
||||
{
|
||||
public:
|
||||
|
||||
std::string operator()(int value) const
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::string operator()(std::unique_ptr<binary_op<add>> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(to_string(), binary->left) + std::string("+")
|
||||
+ util::apply_visitor(to_string(), binary->right);
|
||||
}
|
||||
|
||||
std::string operator()(std::unique_ptr<binary_op<sub>> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(to_string(), binary->left) + std::string("-")
|
||||
+ util::apply_visitor(to_string(), binary->right);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage" << argv[0] << " <num-iter>" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const std::size_t NUM_ITER = static_cast<std::size_t>(std::stol(argv[1]));
|
||||
|
||||
test::expression sum(std::unique_ptr<test::binary_op<test::add>>(new test::binary_op<test::add>(2, 3)));
|
||||
test::expression result(std::unique_ptr<test::binary_op<test::sub>>(new test::binary_op<test::sub>(std::move(sum), 4)));
|
||||
std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl;
|
||||
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
int total = 0;
|
||||
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
||||
{
|
||||
total += util::apply_visitor(test::calculator(), result);
|
||||
}
|
||||
std::cerr << "total=" << total << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Vendored
+306
@@ -0,0 +1,306 @@
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "variant.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
template <typename T>
|
||||
struct mutating_visitor
|
||||
{
|
||||
mutating_visitor(T & val)
|
||||
: val_(val) {}
|
||||
|
||||
void operator() (T & val) const
|
||||
{
|
||||
val = val_;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void operator() (T1& ) const {} // no-op
|
||||
|
||||
T & val_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "variant version", "[variant]" ) {
|
||||
unsigned int version = VARIANT_VERSION;
|
||||
REQUIRE(version == 100);
|
||||
#if VARIANT_VERSION == 100
|
||||
REQUIRE(true);
|
||||
#else
|
||||
REQUIRE(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE( "variant can be moved into vector", "[variant]" ) {
|
||||
typedef util::variant<bool,std::string> variant_type;
|
||||
variant_type v(std::string("test"));
|
||||
std::vector<variant_type> vec;
|
||||
vec.emplace_back(std::move(v));
|
||||
REQUIRE(v.get<std::string>() != std::string("test"));
|
||||
REQUIRE(vec.at(0).get<std::string>() == std::string("test"));
|
||||
}
|
||||
|
||||
TEST_CASE( "variant should support built-in types", "[variant]" ) {
|
||||
SECTION( "bool" ) {
|
||||
util::variant<bool> v(true);
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<bool>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<bool>() == true);
|
||||
v.set<bool>(false);
|
||||
REQUIRE(v.get<bool>() == false);
|
||||
v = true;
|
||||
REQUIRE(v == util::variant<bool>(true));
|
||||
}
|
||||
SECTION( "nullptr" ) {
|
||||
typedef std::nullptr_t value_type;
|
||||
util::variant<value_type> v(nullptr);
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
// TODO: commented since it breaks on windows: 'operator << is ambiguous'
|
||||
//REQUIRE(v.get<value_type>() == nullptr);
|
||||
// FIXME: does not compile: ./variant.hpp:340:14: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::__1::basic_ostream<char>' and 'const nullptr_t')
|
||||
// https://github.com/mapbox/variant/issues/14
|
||||
//REQUIRE(v == util::variant<value_type>(nullptr));
|
||||
}
|
||||
SECTION( "unique_ptr" ) {
|
||||
typedef std::unique_ptr<std::string> value_type;
|
||||
util::variant<value_type> v(value_type(new std::string("hello")));
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(*v.get<value_type>().get() == *value_type(new std::string("hello")).get());
|
||||
}
|
||||
SECTION( "string" ) {
|
||||
typedef std::string value_type;
|
||||
util::variant<value_type> v(value_type("hello"));
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == value_type("hello"));
|
||||
v.set<value_type>(value_type("there"));
|
||||
REQUIRE(v.get<value_type>() == value_type("there"));
|
||||
v = value_type("variant");
|
||||
REQUIRE(v == util::variant<value_type>(value_type("variant")));
|
||||
}
|
||||
SECTION( "size_t" ) {
|
||||
typedef std::size_t value_type;
|
||||
util::variant<value_type> v(std::numeric_limits<value_type>::max());
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
|
||||
v.set<value_type>(value_type(0));
|
||||
REQUIRE(v.get<value_type>() == value_type(0));
|
||||
v = value_type(1);
|
||||
REQUIRE(v == util::variant<value_type>(value_type(1)));
|
||||
}
|
||||
SECTION( "int8_t" ) {
|
||||
typedef std::int8_t value_type;
|
||||
util::variant<value_type> v(std::numeric_limits<value_type>::max());
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
|
||||
v.set<value_type>(0);
|
||||
REQUIRE(v.get<value_type>() == value_type(0));
|
||||
v = value_type(1);
|
||||
REQUIRE(v == util::variant<value_type>(value_type(1)));
|
||||
}
|
||||
SECTION( "int16_t" ) {
|
||||
typedef std::int16_t value_type;
|
||||
util::variant<value_type> v(std::numeric_limits<value_type>::max());
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
|
||||
v.set<value_type>(0);
|
||||
REQUIRE(v.get<value_type>() == value_type(0));
|
||||
v = value_type(1);
|
||||
REQUIRE(v == util::variant<value_type>(value_type(1)));
|
||||
}
|
||||
SECTION( "int32_t" ) {
|
||||
typedef std::int32_t value_type;
|
||||
util::variant<value_type> v(std::numeric_limits<value_type>::max());
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
|
||||
v.set<value_type>(0);
|
||||
REQUIRE(v.get<value_type>() == value_type(0));
|
||||
v = value_type(1);
|
||||
REQUIRE(v == util::variant<value_type>(value_type(1)));
|
||||
}
|
||||
SECTION( "int64_t" ) {
|
||||
typedef std::int64_t value_type;
|
||||
util::variant<value_type> v(std::numeric_limits<value_type>::max());
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<value_type>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
|
||||
v.set<value_type>(0);
|
||||
REQUIRE(v.get<value_type>() == value_type(0));
|
||||
v = value_type(1);
|
||||
REQUIRE(v == util::variant<value_type>(value_type(1)));
|
||||
}
|
||||
}
|
||||
|
||||
struct MissionInteger
|
||||
{
|
||||
typedef uint64_t value_type;
|
||||
value_type val_;
|
||||
public:
|
||||
MissionInteger(uint64_t val) :
|
||||
val_(val) {}
|
||||
|
||||
bool operator==(MissionInteger const& rhs) const
|
||||
{
|
||||
return (val_ == rhs.get());
|
||||
}
|
||||
|
||||
uint64_t get() const
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO - remove after https://github.com/mapbox/variant/issues/14
|
||||
std::ostream& operator<<(std::ostream& os, MissionInteger const& rhs)
|
||||
{
|
||||
os << rhs.get();
|
||||
return os;
|
||||
}
|
||||
|
||||
TEST_CASE( "variant should support custom types", "[variant]" ) {
|
||||
// http://www.missionintegers.com/integer/34838300
|
||||
util::variant<MissionInteger> v(MissionInteger(34838300));
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.is<MissionInteger>());
|
||||
REQUIRE(v.get_type_index() == 0);
|
||||
REQUIRE(v.get<MissionInteger>() == MissionInteger(34838300));
|
||||
REQUIRE(v.get<MissionInteger>().get() == MissionInteger::value_type(34838300));
|
||||
// TODO: should both of the set usages below compile?
|
||||
v.set<MissionInteger>(MissionInteger::value_type(0));
|
||||
v.set<MissionInteger>(MissionInteger(0));
|
||||
REQUIRE(v.get<MissionInteger>().get() == MissionInteger::value_type(0));
|
||||
v = MissionInteger(1);
|
||||
REQUIRE(v == util::variant<MissionInteger>(MissionInteger(1)));
|
||||
}
|
||||
|
||||
// Test internal api
|
||||
TEST_CASE( "variant should correctly index types", "[variant]" ) {
|
||||
typedef util::variant<bool,std::string,std::uint64_t,std::int64_t,double,float> variant_type;
|
||||
// Index is in reverse order
|
||||
REQUIRE(variant_type(true).get_type_index() == 5);
|
||||
REQUIRE(variant_type(std::string("test")).get_type_index() == 4);
|
||||
REQUIRE(variant_type(std::uint64_t(0)).get_type_index() == 3);
|
||||
REQUIRE(variant_type(std::int64_t(0)).get_type_index() == 2);
|
||||
REQUIRE(variant_type(double(0.0)).get_type_index() == 1);
|
||||
REQUIRE(variant_type(float(0.0)).get_type_index() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) {
|
||||
typedef util::variant<int> variant_type;
|
||||
variant_type var = 5;
|
||||
REQUIRE(var.get<int>() == 5);
|
||||
REQUIRE_THROWS(var.get<double>()); // XXX shouldn't this be a compile time error? See https://github.com/mapbox/variant/issues/24
|
||||
}
|
||||
|
||||
TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) {
|
||||
typedef util::variant<int, double> variant_type;
|
||||
variant_type var = 5;
|
||||
REQUIRE(var.get<int>() == 5);
|
||||
REQUIRE_THROWS(var.get<double>());
|
||||
}
|
||||
|
||||
TEST_CASE( "get with wrong type (here: int) should throw", "[variant]" ) {
|
||||
typedef util::variant<int, double> variant_type;
|
||||
variant_type var = 5.0;
|
||||
REQUIRE(var.get<double>() == 5.0);
|
||||
REQUIRE_THROWS(var.get<int>());
|
||||
}
|
||||
|
||||
TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) {
|
||||
typedef util::variant<int> variant_type;
|
||||
variant_type var(5.0); // converted to int
|
||||
REQUIRE(var.get<int>() == 5);
|
||||
REQUIRE_THROWS(var.get<double>());
|
||||
var = 6.0; // works for operator=, too
|
||||
REQUIRE(var.get<int>() == 6);
|
||||
}
|
||||
|
||||
TEST_CASE( "implicit conversion to first type in variant type list", "[variant][implicit conversion]" ) {
|
||||
typedef util::variant<long, char> variant_type;
|
||||
variant_type var = 5.0; // converted to long
|
||||
REQUIRE(var.get<long>() == 5);
|
||||
REQUIRE_THROWS(var.get<char>());
|
||||
REQUIRE_THROWS(var.get<double>());
|
||||
}
|
||||
|
||||
TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) {
|
||||
typedef util::variant<unsigned char> variant_type;
|
||||
variant_type var = 100.0;
|
||||
CHECK(var.get<unsigned char>() == static_cast<unsigned char>(100.0));
|
||||
CHECK(var.get<unsigned char>() == static_cast<unsigned char>(static_cast<unsigned int>(100.0)));
|
||||
}
|
||||
|
||||
struct dummy {};
|
||||
|
||||
TEST_CASE( "variant value traits", "[variant::detail]" ) {
|
||||
// Users should not create variants with duplicated types
|
||||
// however our type indexing should still work
|
||||
// Index is in reverse order
|
||||
REQUIRE((util::detail::value_traits<bool, bool, int, double, std::string>::index == 3));
|
||||
REQUIRE((util::detail::value_traits<int, bool, int, double, std::string>::index == 2));
|
||||
REQUIRE((util::detail::value_traits<double, bool, int, double, std::string>::index == 1));
|
||||
REQUIRE((util::detail::value_traits<std::string, bool, int, double, std::string>::index == 0));
|
||||
REQUIRE((util::detail::value_traits<dummy, bool, int, double, std::string>::index == util::detail::invalid_value));
|
||||
REQUIRE((util::detail::value_traits<std::vector<int>, bool, int, double, std::string>::index == util::detail::invalid_value));
|
||||
}
|
||||
|
||||
TEST_CASE( "variant default constructor", "[variant][default constructor]" ) {
|
||||
// By default variant is initialised with (default constructed) first type in template parameters pack
|
||||
// As a result first type in Types... must be default constructable
|
||||
// NOTE: index in reverse order -> index = N - 1
|
||||
REQUIRE((util::variant<int, double, std::string>().get_type_index() == 2));
|
||||
REQUIRE((util::variant<int, double, std::string>(util::no_init()).get_type_index() == util::detail::invalid_value));
|
||||
}
|
||||
|
||||
TEST_CASE( "variant visitation", "[visitor][unary visitor]" ) {
|
||||
util::variant<int, double, std::string> var(123);
|
||||
REQUIRE(var.get<int>() == 123);
|
||||
int val = 456;
|
||||
mutating_visitor<int> visitor(val);
|
||||
util::apply_visitor(visitor, var);
|
||||
REQUIRE(var.get<int>() == 456);
|
||||
}
|
||||
|
||||
TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) {
|
||||
typedef util::variant<int, double, std::string> variant_type;
|
||||
std::vector<variant_type> var = {2.1, 123, "foo", 456};
|
||||
std::stringstream out;
|
||||
std::copy(var.begin(), var.end(), std::ostream_iterator<variant_type>(out, ","));
|
||||
out << var[2];
|
||||
REQUIRE(out.str() == "2.1,123,foo,456,foo");
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char* const argv[])
|
||||
{
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n");
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "variant.hpp"
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
struct check : util::static_visitor<>
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T const& val) const
|
||||
{
|
||||
if (val != 0) throw std::runtime_error("invalid");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
typedef util::variant<bool, int, double> variant_type;
|
||||
variant_type v(0);
|
||||
util::apply_visitor(check(), v);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user