diff --git a/test/t/unary_visitor.cpp b/test/t/unary_visitor.cpp index 8df6110..8996ab6 100644 --- a/test/t/unary_visitor.cpp +++ b/test/t/unary_visitor.cpp @@ -125,3 +125,25 @@ TEST_CASE("changes in const visitor (with mutable internals) should be visible", REQUIRE(mapbox::util::apply_visitor(ts, v) == sizeof(std::string)); REQUIRE(ts.result() == sizeof(std::string)); } + +struct is_uninitialized_visitor +{ + bool operator() () const { return true; } + + template + bool operator() (T const& ) const { return false; } +}; + +TEST_CASE("apply_visitor on uninitialized variant", "[visitor][unary visitor]") +{ + namespace mu = mapbox::util; + using variant_type = mu::variant; + variant_type v{mu::no_init()}; + + // total_sizeof doesn't have operator()() + CHECK_THROWS_AS(mu::apply_visitor(total_sizeof(), v), mu::bad_variant_access); + + // is_uninitialied_visitor has operator()() + REQUIRE_NOTHROW(mu::apply_visitor(is_uninitialized_visitor(), v)); + CHECK(mu::apply_visitor(is_uninitialized_visitor(), v) == true); +} diff --git a/variant.hpp b/variant.hpp index db5d3c8..bc4ce97 100644 --- a/variant.hpp +++ b/variant.hpp @@ -67,6 +67,10 @@ class bad_variant_access : public std::runtime_error }; // class bad_variant_access +struct no_init +{ +}; + template struct MAPBOX_VARIANT_DEPRECATED static_visitor { @@ -289,6 +293,24 @@ struct unwrapper> } }; +template +struct dispatch_no_init +{ + VARIANT_INLINE static R apply(F&&) + { + throw bad_variant_access("apply_visitor on uninitialized variant"); + } +}; + +template +struct dispatch_no_init()()))> +{ + VARIANT_INLINE static R apply(F&& f) + { + return f(); + } +}; + template struct dispatcher; @@ -320,17 +342,17 @@ struct dispatcher } }; -template -struct dispatcher +template +struct dispatcher { - VARIANT_INLINE static R apply_const(V const& v, F&& f) + VARIANT_INLINE static R apply_const(V const&, F&& f) { - return f(unwrapper::apply_const(v.template get())); + return dispatch_no_init::apply(std::forward(f)); } - VARIANT_INLINE static R apply(V& v, F&& f) + VARIANT_INLINE static R apply(V&, F&& f) { - return f(unwrapper::apply(v.template get())); + return dispatch_no_init::apply(std::forward(f)); } }; @@ -551,10 +573,6 @@ struct static_none_of : std::is_same class variant {