Bump mapbox/variant to version 1.2.0 (#6898)
This commit is contained in:
committed by
GitHub
parent
babdced52f
commit
8b48e2ccc6
@@ -1,4 +1,4 @@
|
||||
// @EXPECTED: enable_if
|
||||
// @EXPECTED: no matching .*\<function for call to .*\<get\>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @EXPECTED: const int
|
||||
// @EXPECTED: no matching function for call to .*\<apply_visitor\>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
|
||||
+8876
-9067
File diff suppressed because it is too large
Load Diff
+155
@@ -10,6 +10,15 @@
|
||||
|
||||
using namespace mapbox::util;
|
||||
|
||||
template <typename T>
|
||||
struct tag
|
||||
{
|
||||
static void dump(const char* prefix)
|
||||
{
|
||||
std::cout << prefix << ": " << typeid(tag<T>).name() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Left, typename Right>
|
||||
using Either = mapbox::util::variant<Left, Right>;
|
||||
|
||||
@@ -55,6 +64,37 @@ void test_singleton_variant()
|
||||
apply_visitor(make_visitor([](int) {}), singleton);
|
||||
}
|
||||
|
||||
// See #180
|
||||
struct test_call_nonconst_member_visitor
|
||||
{
|
||||
template <typename T>
|
||||
void operator() (T & obj) const
|
||||
{
|
||||
tag<decltype(obj)>::dump("test_call_nonconst_member: visitor");
|
||||
obj.foo();
|
||||
}
|
||||
};
|
||||
|
||||
void test_call_nonconst_member()
|
||||
{
|
||||
struct object
|
||||
{
|
||||
void foo() { val = 42;}
|
||||
int val = 0;
|
||||
};
|
||||
|
||||
variant<object> v = object{};
|
||||
apply_visitor(test_call_nonconst_member_visitor{}, v);
|
||||
|
||||
#ifdef HAS_CPP14_SUPPORT
|
||||
apply_visitor([](auto& obj)
|
||||
{
|
||||
tag<decltype(obj)>::dump("test_call_nonconst_member: lambda");
|
||||
obj.foo();
|
||||
}, v);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_lambda_overloads_sfinae()
|
||||
#ifdef HAS_CPP14_SUPPORT
|
||||
{
|
||||
@@ -85,6 +125,9 @@ void test_match_singleton()
|
||||
{
|
||||
variant<int> singleton = 5;
|
||||
singleton.match([](int) {});
|
||||
|
||||
auto lambda = [](int) {};
|
||||
singleton.match(lambda);
|
||||
}
|
||||
|
||||
void test_match_overloads()
|
||||
@@ -112,16 +155,128 @@ void test_match_overloads_capture()
|
||||
std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
|
||||
}
|
||||
|
||||
struct MovableOnly
|
||||
{
|
||||
MovableOnly() = default;
|
||||
|
||||
MovableOnly(MovableOnly&&) = default;
|
||||
MovableOnly& operator=(MovableOnly&&) = default;
|
||||
};
|
||||
|
||||
struct MovableCopyable
|
||||
{
|
||||
MovableCopyable() = default;
|
||||
|
||||
MovableCopyable(MovableCopyable&&) = default;
|
||||
MovableCopyable& operator=(MovableCopyable&&) = default;
|
||||
|
||||
MovableCopyable(const MovableCopyable&) = default;
|
||||
MovableCopyable& operator=(const MovableCopyable&) = default;
|
||||
};
|
||||
|
||||
void test_match_overloads_init_capture()
|
||||
#ifdef HAS_CPP14_SUPPORT
|
||||
{
|
||||
Either<Error, Response> rv;
|
||||
|
||||
rv = Error{};
|
||||
|
||||
rv.match([p = MovableOnly{}](auto&&) {});
|
||||
{
|
||||
auto lambda = [p = MovableCopyable{}](auto&&) {};
|
||||
rv.match(lambda);
|
||||
|
||||
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
|
||||
[p = MovableOnly{}](Error) { std::cout << "Error\n"; });
|
||||
}
|
||||
{
|
||||
auto lambda = [](Error) { std::cout << "Error\n"; };
|
||||
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
|
||||
lambda);
|
||||
rv.match(lambda,
|
||||
[p = MovableOnly{}](Response) { std::cout << "Response\n"; });
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// See #140
|
||||
void test_match_overloads_otherwise()
|
||||
#ifdef HAS_CPP14_SUPPORT
|
||||
{
|
||||
|
||||
struct Center
|
||||
{
|
||||
};
|
||||
struct Indent
|
||||
{
|
||||
};
|
||||
struct Justify
|
||||
{
|
||||
};
|
||||
struct None
|
||||
{
|
||||
};
|
||||
|
||||
using Properties = mapbox::util::variant<Center, Indent, Justify, None>;
|
||||
|
||||
Properties props = Justify{};
|
||||
|
||||
props.match([&](Center) { std::cout << "Center\n"; }, //
|
||||
[&](Indent) { std::cout << "Indent\n"; }, //
|
||||
[&](auto&&) { std::cout << "Otherwise\n"; }); //
|
||||
}
|
||||
#else
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename>
|
||||
struct Moveable
|
||||
{
|
||||
Moveable() = default; // Default constructible
|
||||
|
||||
Moveable(const Moveable&) = delete; // Disable copy ctor
|
||||
Moveable& operator=(const Moveable&) = delete; // Disable copy assign op
|
||||
|
||||
Moveable(Moveable&&) = default; // Enable move ctor
|
||||
Moveable& operator=(Moveable&&) = default; // Enable move assign op
|
||||
};
|
||||
|
||||
void test_match_move_out_of_variant()
|
||||
{
|
||||
// Distinguishable at type level
|
||||
using T1 = Moveable<struct Tag1>;
|
||||
using T2 = Moveable<struct Tag2>;
|
||||
using T3 = mapbox::util::recursive_wrapper<int>;
|
||||
|
||||
mapbox::util::variant<T1, T2> v = T1{};
|
||||
|
||||
std::move(v).match([](T1&&) {}, // Consume T1 by value
|
||||
[](T2&&) {}); // Consume T2 by value
|
||||
|
||||
mapbox::util::variant<T3, T2> w = T2{};
|
||||
|
||||
std::move(w).match([](int&&) {}, // Consume unwrapped int
|
||||
[](T2&&) {}); // Consume T2 by value
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_lambda_overloads();
|
||||
test_singleton_variant();
|
||||
test_call_nonconst_member();
|
||||
test_lambda_overloads_capture();
|
||||
test_lambda_overloads_sfinae();
|
||||
|
||||
test_match_singleton();
|
||||
test_match_overloads();
|
||||
test_match_overloads_capture();
|
||||
test_match_overloads_init_capture();
|
||||
test_match_overloads_otherwise();
|
||||
test_match_move_out_of_variant();
|
||||
}
|
||||
|
||||
#undef HAS_CPP14_SUPPORT
|
||||
|
||||
+4
-5
@@ -1,4 +1,3 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@@ -64,12 +63,12 @@ struct calculator
|
||||
|
||||
int operator()(binary_op<add> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary.left) + util::apply_visitor(calculator(), binary.right);
|
||||
return util::apply_visitor(*this, binary.left) + util::apply_visitor(*this, binary.right);
|
||||
}
|
||||
|
||||
int operator()(binary_op<sub> const& binary) const
|
||||
{
|
||||
return util::apply_visitor(calculator(), binary.left) - util::apply_visitor(calculator(), binary.right);
|
||||
return util::apply_visitor(*this, binary.left) - util::apply_visitor(*this, binary.right);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,12 +82,12 @@ struct to_string
|
||||
|
||||
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);
|
||||
return util::apply_visitor(*this, binary.left) + std::string("+") + util::apply_visitor(*this, 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);
|
||||
return util::apply_visitor(*this, binary.left) + std::string("-") + util::apply_visitor(*this, binary.right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -160,8 +160,8 @@ struct swap_visitor
|
||||
{
|
||||
using T = typename std::common_type<A, B>::type;
|
||||
T tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
a = static_cast<A>(b);
|
||||
b = static_cast<B>(tmp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+1
-3
@@ -46,9 +46,7 @@ TEST_CASE("set() works cleanly even if the constructor throws ", "[variant]")
|
||||
variant_type v = obj;
|
||||
REQUIRE(v.is<t1>());
|
||||
REQUIRE(v.get<t1>().value == 42);
|
||||
REQUIRE_THROWS({
|
||||
v.set<t2>(13);
|
||||
});
|
||||
REQUIRE_THROWS(v.set<t2>(13));
|
||||
}
|
||||
REQUIRE(count == 0);
|
||||
}
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
using namespace mapbox;
|
||||
|
||||
namespace test {
|
||||
|
||||
struct t_noexcept_true_1 {
|
||||
t_noexcept_true_1(t_noexcept_true_1&&) noexcept = default;
|
||||
t_noexcept_true_1& operator=(t_noexcept_true_1&&) noexcept = default;
|
||||
};
|
||||
|
||||
struct t_noexcept_true_2 {
|
||||
t_noexcept_true_2(t_noexcept_true_2&&) noexcept = default;
|
||||
t_noexcept_true_2& operator=(t_noexcept_true_2&&) noexcept = default;
|
||||
};
|
||||
|
||||
struct t_noexcept_false_1 {
|
||||
t_noexcept_false_1(t_noexcept_false_1&&) noexcept(false) {}
|
||||
t_noexcept_false_1& operator=(t_noexcept_false_1&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
using should_be_no_throw_copyable = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
|
||||
static_assert(std::is_nothrow_move_assignable<should_be_no_throw_copyable>::value,
|
||||
"variants with no-throw move assignable types should be "
|
||||
"no-throw move nothrow assignable");
|
||||
|
||||
using should_be_no_throw_assignable = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
|
||||
static_assert(std::is_nothrow_move_constructible<should_be_no_throw_assignable>::value,
|
||||
"variants with no-throw move assignable types should be "
|
||||
"no-throw move nothrow assignable");
|
||||
|
||||
using should_not_be_no_throw_copyable = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
|
||||
static_assert(not std::is_nothrow_move_assignable<should_not_be_no_throw_copyable>::value,
|
||||
"variants with no-throw move assignable types should be "
|
||||
"no-throw move nothrow assignable");
|
||||
|
||||
using should_not_be_no_throw_assignable = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
|
||||
static_assert(not std::is_nothrow_move_constructible<should_not_be_no_throw_assignable>::value,
|
||||
"variants with no-throw move assignable types should be "
|
||||
"no-throw move nothrow assignable");
|
||||
|
||||
|
||||
// this type cannot be nothrow converted from either of its types, even the nothrow moveable one,
|
||||
// because the conversion operator moves the whole variant.
|
||||
using convertable_test_type = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
|
||||
|
||||
// this type can be nothrow converted from either of its types.
|
||||
using convertable_test_type_2 = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
|
||||
|
||||
static_assert(not std::is_nothrow_assignable<convertable_test_type, t_noexcept_true_1>::value,
|
||||
"variants with noexcept(true) move constructible types should be nothrow-convertible "
|
||||
"from those types only IF the variant itself is nothrow_move_assignable");
|
||||
|
||||
static_assert(not std::is_nothrow_assignable<convertable_test_type, t_noexcept_false_1>::value,
|
||||
"variants with noexcept(false) move constructible types should not be nothrow-convertible "
|
||||
"from those types");
|
||||
|
||||
static_assert(std::is_nothrow_assignable<convertable_test_type_2, t_noexcept_true_2>::value,
|
||||
"variants with noexcept(true) move constructible types should be nothrow-convertible "
|
||||
"from those types only IF the variant itself is nothrow_move_assignable");
|
||||
|
||||
|
||||
} // namespace test
|
||||
+2
-1
@@ -1,4 +1,3 @@
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapbox/optional.hpp>
|
||||
@@ -97,6 +96,8 @@ TEST_CASE("self assignment", "[optional]")
|
||||
|
||||
a = 1;
|
||||
REQUIRE(a.get() == 1);
|
||||
#if !defined(__clang__)
|
||||
a = a;
|
||||
REQUIRE(a.get() == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
+29
-2
@@ -1,6 +1,6 @@
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
#include <mapbox/recursive_wrapper.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
@@ -153,6 +153,33 @@ TEST_CASE("recursive wrapper of pair<int, int>")
|
||||
b = std::move(c);
|
||||
REQUIRE(b.get().first == 5);
|
||||
REQUIRE(b.get().second == 6);
|
||||
// REQUIRE(c.get_pointer() == nullptr);
|
||||
//REQUIRE(c.get_pointer() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("Multiple recurssive wrappers of polymorphic types")
|
||||
{
|
||||
// https://github.com/mapbox/variant/issues/146
|
||||
// (Visual Studio 2015 update 3)
|
||||
using namespace mapbox::util;
|
||||
struct Base;
|
||||
struct Derived;
|
||||
using Variant = variant<recursive_wrapper<Base>, recursive_wrapper<Derived>>;
|
||||
struct Base { };
|
||||
struct Derived : public Base { };
|
||||
{
|
||||
Base base;
|
||||
Derived derived;
|
||||
Variant v;
|
||||
v = base;
|
||||
v = derived; // compile error prior https://github.com/mapbox/variant/pull/147
|
||||
CHECK(v.is<Derived>());
|
||||
}
|
||||
{
|
||||
Derived derived;
|
||||
Variant v(derived); // compile error prior https://github.com/mapbox/variant/pull/147
|
||||
CHECK(v.is<Derived>());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -15,7 +14,7 @@ struct some_struct
|
||||
std::string c;
|
||||
};
|
||||
|
||||
using variant_internal_index_type = size_t;
|
||||
using variant_internal_index_type = mapbox::util::type_index_t;
|
||||
|
||||
TEST_CASE("size of variants")
|
||||
{
|
||||
|
||||
+21
-63
@@ -208,9 +208,7 @@ TEST_CASE("get with wrong type (here: double) should throw", "[variant]")
|
||||
REQUIRE(var.is<int>());
|
||||
REQUIRE_FALSE(var.is<double>());
|
||||
REQUIRE(var.get<int>() == 5);
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<double>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<double>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -222,13 +220,9 @@ TEST_CASE("get with wrong type (here: int) should throw", "[variant]")
|
||||
REQUIRE_FALSE(var.is<int>());
|
||||
REQUIRE(var.get<double>() == 5.0);
|
||||
REQUIRE(mapbox::util::get<double>(var) == 5.0);
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<int>(var);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<int>(var),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -240,26 +234,18 @@ TEST_CASE("get on const varint with wrong type (here: int) should throw", "[vari
|
||||
REQUIRE_FALSE(var.is<int>());
|
||||
REQUIRE(var.get<double>() == 5.0);
|
||||
REQUIRE(mapbox::util::get<double>(var) == 5.0);
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<int>(var);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<int>(var),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
TEST_CASE("get with any type should throw if not initialized", "[variant]")
|
||||
{
|
||||
mapbox::util::variant<int, double> var{mapbox::util::no_init()};
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<double>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<double>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -273,16 +259,12 @@ TEST_CASE("no_init variant can be copied and moved from", "[variant]")
|
||||
|
||||
REQUIRE(v2.get<int>() == 42);
|
||||
v2 = v1;
|
||||
REQUIRE_THROWS_AS({
|
||||
v2.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v2.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
|
||||
REQUIRE(v3.get<int>() == 23);
|
||||
v3 = std::move(v1);
|
||||
REQUIRE_THROWS_AS({
|
||||
v3.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v3.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -294,9 +276,7 @@ TEST_CASE("no_init variant can be copied and moved to", "[variant]")
|
||||
variant_type v2{mapbox::util::no_init()};
|
||||
variant_type v3{mapbox::util::no_init()};
|
||||
|
||||
REQUIRE_THROWS_AS({
|
||||
v2.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v2.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
|
||||
REQUIRE(v1.get<int>() == 42);
|
||||
@@ -304,9 +284,7 @@ TEST_CASE("no_init variant can be copied and moved to", "[variant]")
|
||||
REQUIRE(v2.get<int>() == 42);
|
||||
REQUIRE(v1.get<int>() == 42);
|
||||
|
||||
REQUIRE_THROWS_AS({
|
||||
v3.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v3.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
|
||||
v3 = std::move(v1);
|
||||
@@ -327,9 +305,7 @@ TEST_CASE("implicit conversion to first type in variant type list", "[variant][i
|
||||
using variant_type = mapbox::util::variant<long, char>;
|
||||
variant_type var = 5l; // converted to long
|
||||
REQUIRE(var.get<long>() == 5);
|
||||
REQUIRE_THROWS_AS({
|
||||
var.get<char>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(var.get<char>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -498,13 +474,9 @@ TEST_CASE("storing reference wrappers works")
|
||||
variant_type v{std::ref(a)};
|
||||
REQUIRE(v.get<int>() == 1);
|
||||
REQUIRE(mapbox::util::get<int>(v) == 1);
|
||||
REQUIRE_THROWS_AS({
|
||||
v.get<double>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v.get<double>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<double>(v);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<double>(v),
|
||||
mapbox::util::bad_variant_access&);
|
||||
a = 2;
|
||||
REQUIRE(v.get<int>() == 2);
|
||||
@@ -515,13 +487,9 @@ TEST_CASE("storing reference wrappers works")
|
||||
v = std::ref(b);
|
||||
REQUIRE(v.get<double>() == Approx(3.141));
|
||||
REQUIRE(mapbox::util::get<double>(v) == Approx(3.141));
|
||||
REQUIRE_THROWS_AS({
|
||||
v.get<int>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v.get<int>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<int>(v);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<int>(v),
|
||||
mapbox::util::bad_variant_access&);
|
||||
b = 2.718;
|
||||
REQUIRE(v.get<double>() == Approx(2.718));
|
||||
@@ -530,9 +498,7 @@ TEST_CASE("storing reference wrappers works")
|
||||
v.get<double>() = 4.1;
|
||||
REQUIRE(b == Approx(4.1));
|
||||
|
||||
REQUIRE_THROWS_AS({
|
||||
v.get<int>() = 4;
|
||||
},
|
||||
REQUIRE_THROWS_AS(v.get<int>() = 4,
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
@@ -546,26 +512,18 @@ TEST_CASE("storing reference wrappers to consts works")
|
||||
REQUIRE(v.get<int>() == 1);
|
||||
REQUIRE(mapbox::util::get<int const>(v) == 1);
|
||||
REQUIRE(mapbox::util::get<int>(v) == 1);
|
||||
REQUIRE_THROWS_AS({
|
||||
v.get<double const>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v.get<double const>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<double const>(v);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<double const>(v),
|
||||
mapbox::util::bad_variant_access&);
|
||||
|
||||
double b = 3.141;
|
||||
v = std::cref(b);
|
||||
REQUIRE(v.get<double const>() == Approx(3.141));
|
||||
REQUIRE(mapbox::util::get<double const>(v) == Approx(3.141));
|
||||
REQUIRE_THROWS_AS({
|
||||
v.get<int const>();
|
||||
},
|
||||
REQUIRE_THROWS_AS(v.get<int const>(),
|
||||
mapbox::util::bad_variant_access&);
|
||||
REQUIRE_THROWS_AS({
|
||||
mapbox::util::get<int const>(v);
|
||||
},
|
||||
REQUIRE_THROWS_AS(mapbox::util::get<int const>(v),
|
||||
mapbox::util::bad_variant_access&);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
#include <mapbox/variant_io.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("variant_alternative", "[types]")
|
||||
{
|
||||
using variant_type = mapbox::util::variant<int, double, std::string>;
|
||||
using type_0 = mapbox::util::variant_alternative<0, variant_type>::type;
|
||||
using type_1 = mapbox::util::variant_alternative<1, variant_type>::type;
|
||||
using type_2 = mapbox::util::variant_alternative<2, variant_type>::type;
|
||||
//using type_3 = mapbox::util::variant_alternative<3, variant_type>::type; // compile error
|
||||
constexpr bool check_0 = std::is_same<int, type_0>::value;
|
||||
constexpr bool check_1 = std::is_same<double, type_1>::value;
|
||||
constexpr bool check_2 = std::is_same<std::string, type_2>::value;
|
||||
CHECK(check_0);
|
||||
CHECK(check_1);
|
||||
CHECK(check_2);
|
||||
}
|
||||
|
||||
TEST_CASE("variant_size", "[types]")
|
||||
{
|
||||
constexpr auto value_0 = mapbox::util::variant_size<mapbox::util::variant<>>::value;
|
||||
constexpr auto value_1 = mapbox::util::variant_size<mapbox::util::variant<int>>::value;
|
||||
constexpr auto value_2 = mapbox::util::variant_size<mapbox::util::variant<int, std::string>>::value;
|
||||
CHECK(value_0 == 0);
|
||||
CHECK(value_1 == 1);
|
||||
CHECK(value_2 == 2);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
using namespace mapbox::util;
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename... T>
|
||||
struct tag {};
|
||||
|
||||
struct deduced_result_visitor
|
||||
{
|
||||
template <typename T>
|
||||
tag<T> operator() (T);
|
||||
|
||||
template <typename T>
|
||||
tag<T const> operator() (T) const;
|
||||
|
||||
template <typename T, typename U>
|
||||
tag<T, U> operator() (T, U);
|
||||
|
||||
template <typename T, typename U>
|
||||
tag<T, U const> operator() (T, U) const;
|
||||
};
|
||||
|
||||
struct explicit_result_visitor : deduced_result_visitor
|
||||
{
|
||||
using result_type = tag<float>;
|
||||
};
|
||||
|
||||
// Doing this compile-time test via assignment to typed tag objects gives
|
||||
// more useful error messages when something goes wrong, than std::is_same
|
||||
// in a static_assert would. Here if result_of_unary_visit returns anything
|
||||
// other than the expected type on the left hand side, the conversion error
|
||||
// message will tell you exactly what it was.
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
|
||||
tag<int> d1m = detail::result_of_unary_visit<deduced_result_visitor, int>{};
|
||||
tag<int const> d1c = detail::result_of_unary_visit<deduced_result_visitor const, int>{};
|
||||
|
||||
tag<float> e1m = detail::result_of_unary_visit<explicit_result_visitor, int>{};
|
||||
tag<float> e1c = detail::result_of_unary_visit<explicit_result_visitor const, int>{};
|
||||
|
||||
tag<int, int> d2m = detail::result_of_binary_visit<deduced_result_visitor, int>{};
|
||||
tag<int, int const> d2c = detail::result_of_binary_visit<deduced_result_visitor const, int>{};
|
||||
|
||||
tag<float> e2m = detail::result_of_binary_visit<explicit_result_visitor, int>{};
|
||||
tag<float> e2c = detail::result_of_binary_visit<explicit_result_visitor const, int>{};
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user