From 76674a359410e5d6af1f52cff115f528ad8ca4d0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 4 Mar 2015 12:48:18 +0100 Subject: [PATCH] Squashed 'third_party/variant/' changes from 24dcab2..3b02ca0 3b02ca0 add which() method returning zero based index of stored T in Types... for boost::variant() compatibility c117592 update unit test to match c64c74775a80474f2012c1a49ab2865e3666107a 36f1e12 add get() overloads for when T is stored in recursive_wrapper also makes get() a compile time error where T is not in Types... (ref #24) 7dfdfa2 clean up coverage files in test directory too [skip ci] 89f8a41 add coverage report git-subtree-dir: third_party/variant git-subtree-split: 3b02ca0e3ab1a36dd6ec9138e7f93eb3176ae5f7 --- Makefile | 2 ++ README.md | 1 + test/unit.cpp | 16 ++++++++++++---- variant.hpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 69761034c..cae3d46bd 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,8 @@ clean: rm -rf *.dSYM rm -f unit.gc* rm -f *gcov + rm -f test/unit.gc* + rm -f test/*gcov pgo: out Makefile variant.hpp $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate diff --git a/README.md b/README.md index 018163c1c..791131d39 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ An alternative to `boost::variant` for C++11. [![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) [![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) +[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master)](https://coveralls.io/r/mapbox/variant?branch=master) # Why use Mapbox Variant? diff --git a/test/unit.cpp b/test/unit.cpp index 3998e6a9b..9b874c707 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -212,11 +212,22 @@ TEST_CASE( "variant should correctly index types", "[variant]" ) { REQUIRE(variant_type(float(0.0)).get_type_index() == 0); } +// Test internal api +TEST_CASE( "variant::which() returns zero based index of stored type", "[variant]" ) { + typedef util::variant variant_type; + // Index is in reverse order + REQUIRE(variant_type(true).which() == 0); + REQUIRE(variant_type(std::string("test")).which() == 1); + REQUIRE(variant_type(std::uint64_t(0)).which() == 2); + REQUIRE(variant_type(std::int64_t(0)).which() == 3); + REQUIRE(variant_type(double(0.0)).which() == 4); + REQUIRE(variant_type(float(0.0)).which() == 5); +} + TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) { typedef util::variant variant_type; variant_type var = 5; REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); // 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]" ) { @@ -237,7 +248,6 @@ TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) { typedef util::variant variant_type; variant_type var(5.0); // converted to int REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); var = 6.0; // works for operator=, too REQUIRE(var.get() == 6); } @@ -247,7 +257,6 @@ TEST_CASE( "implicit conversion to first type in variant type list", "[variant][ variant_type var = 5.0; // converted to long REQUIRE(var.get() == 5); REQUIRE_THROWS(var.get()); - REQUIRE_THROWS(var.get()); } TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) { @@ -297,7 +306,6 @@ TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) { REQUIRE(out.str() == "2.1,123,foo,456,foo"); } - int main (int argc, char* const argv[]) { int result = Catch::Session().run(argc, argv); diff --git a/variant.hpp b/variant.hpp index 880ca1b2a..a3cdea63a 100644 --- a/variant.hpp +++ b/variant.hpp @@ -601,7 +601,8 @@ public: type_index = detail::direct_type::index; } - template + // get() + template::index != detail::invalid_value)>::type* = nullptr> VARIANT_INLINE T& get() { if (type_index == detail::direct_type::index) @@ -610,11 +611,13 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get()"); } } - template + template ::index != detail::invalid_value) + >::type* = nullptr> VARIANT_INLINE T const& get() const { if (type_index == detail::direct_type::index) @@ -623,15 +626,50 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get()"); } } + // get() - T stored as recursive_wrapper + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T& get() + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } + + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T const& get() const + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast const*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } VARIANT_INLINE std::size_t get_type_index() const { return type_index; } + VARIANT_INLINE int which() const noexcept + { + return static_cast(sizeof...(Types) - type_index - 1); + } + // visitor // unary template @@ -738,13 +776,13 @@ auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::bin // getter interface template -ResultType & get(T & var) +ResultType & get(T & var) { return var.template get(); } template -ResultType const& get(T const& var) +ResultType const& get(T const& var) { return var.template get(); }