From 6c5596c0bb0865eed054fb13e5f091883a76409f Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Mon, 5 Mar 2018 23:33:12 +0100 Subject: [PATCH 1/8] Added global "variant_cast" method Added 4 overloads of the method "variant_cast" In order to move values out, to return values by reference or to return a pointer to the underlying values, when the type does match: template T variant_cast(variant&& operand); template T variant_cast(variant& operand); template T variant_cast(const variant& operand); template const T* variant_cast(const variant* operand) RTTR_NOEXCEPT; template T* variant_cast(variant* operand) RTTR_NOEXCEPT; Additionally: - added non-const version of variant::get_value() - fixed copy-right year in root CMakeLists.txt file Fixes #108 --- CMakeLists.txt | 2 +- src/rttr/detail/variant/variant_data_policy.h | 4 +- src/rttr/detail/variant/variant_impl.h | 113 ++++++++- src/rttr/variant.h | 125 ++++++++++ src/unit_tests/unit_tests.cmake | 1 + src/unit_tests/variant/variant_cast_test.cpp | 232 ++++++++++++++++++ src/unit_tests/variant/variant_misc_test.cpp | 30 +++ 7 files changed, 500 insertions(+), 7 deletions(-) create mode 100644 src/unit_tests/variant/variant_cast_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0824efa6..1af95a8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ #################################################################################### # # -# Copyright (c) 2014, 2015 - 2017 Axel Menzel # +# Copyright (c) 2014 - 2018 Axel Menzel # # # # This file is part of RTTR (Run Time Type Reflection) # # License: MIT License # diff --git a/src/rttr/detail/variant/variant_data_policy.h b/src/rttr/detail/variant/variant_data_policy.h index 8b2da01a..d61271f4 100644 --- a/src/rttr/detail/variant/variant_data_policy.h +++ b/src/rttr/detail/variant/variant_data_policy.h @@ -652,7 +652,7 @@ struct RTTR_API variant_data_policy_empty } case variant_policy_operation::GET_VALUE: { - arg.get_value() = nullptr; + arg.get_value() = nullptr; break; } case variant_policy_operation::GET_TYPE: @@ -767,7 +767,7 @@ struct RTTR_API variant_data_policy_void } case variant_policy_operation::GET_VALUE: { - arg.get_value() = nullptr; + arg.get_value() = nullptr; break; } case variant_policy_operation::GET_TYPE: diff --git a/src/rttr/detail/variant/variant_impl.h b/src/rttr/detail/variant/variant_impl.h index 58decfbb..f56c591b 100644 --- a/src/rttr/detail/variant/variant_impl.h +++ b/src/rttr/detail/variant/variant_impl.h @@ -40,6 +40,11 @@ namespace rttr { +namespace detail +{ +template +using variant_t = detail::remove_cv_t>; +} ///////////////////////////////////////////////////////////////////////////////////////// @@ -130,13 +135,26 @@ RTTR_INLINE bool variant::operator>(const variant& other) const ///////////////////////////////////////////////////////////////////////////////////////// +template +RTTR_INLINE T& variant::get_value() +{ + using namespace detail; + auto result = unsafe_variant_cast>(this); + + using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + return *result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + template RTTR_INLINE const T& variant::get_value() const { - const void* value; - m_policy(detail::variant_policy_operation::GET_VALUE, m_data, value); - using nonRef = detail::remove_cv_t; - return *reinterpret_cast(value); + using namespace detail; + auto result = unsafe_variant_cast>(this); + + using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + return *result; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -390,6 +408,93 @@ RTTR_INLINE T variant::convert(bool* ok) const return convert_impl(ok); } +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +namespace detail +{ + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE T* unsafe_variant_cast(variant* operand) RTTR_NOEXCEPT +{ + const void* value; + operand->m_policy(detail::variant_policy_operation::GET_VALUE, operand->m_data, value); + return reinterpret_cast(const_cast(value)); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE const T* unsafe_variant_cast(const variant* operand) RTTR_NOEXCEPT +{ + return unsafe_variant_cast(const_cast(operand)); +} + +} // end namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE T variant_cast(const variant& operand) +{ + using namespace detail; + static_assert(std::is_constructible&>::value, + "variant_cast(variant&) requires T to be constructible from const remove_cv_t>&"); + + auto result = unsafe_variant_cast>(&operand); + + using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + return static_cast(*result); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE T variant_cast(variant& operand) +{ + using namespace detail; + static_assert(std::is_constructible&>::value, + "variant_cast(variant&) requires T to be constructible from remove_cv_t>&"); + + auto result = unsafe_variant_cast>(&operand); + + using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + return static_cast(*result); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE T variant_cast(variant&& operand) +{ + using namespace detail; + static_assert(std::is_constructible>::value, + "variant_cast(variant&&) requires T to be constructible from remove_cv_t>"); + auto result = unsafe_variant_cast>(&operand); + return std::move(*result); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE T* variant_cast(variant* operand) RTTR_NOEXCEPT +{ + using namespace detail; + return (type::get() == operand->get_type()) ? + unsafe_variant_cast(operand) : nullptr; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +template +RTTR_INLINE const T* variant_cast(const variant* operand) RTTR_NOEXCEPT +{ + return variant_cast(const_cast(operand)); +} + ///////////////////////////////////////////////////////////////////////////////////////// } // end namespace rttr diff --git a/src/rttr/variant.h b/src/rttr/variant.h index b0a2fac1..f2ce9d21 100644 --- a/src/rttr/variant.h +++ b/src/rttr/variant.h @@ -52,6 +52,11 @@ class instance; namespace detail { + template + RTTR_INLINE T* unsafe_variant_cast(variant* operand) RTTR_NOEXCEPT; + template + RTTR_INLINE const T* unsafe_variant_cast(const variant* operand) RTTR_NOEXCEPT; + struct data_address_container; template struct empty_type_converter; @@ -423,6 +428,32 @@ class RTTR_API variant */ bool is_sequential_container() const; + /*! + * \brief Returns a reference to the containing value as type \p T. + * + * \code{.cpp} + * struct custom_type + * { + * //... + * }; + * + * variant var = custom_type{}; + * if (var.is_type()) // yields to true + * custom_type& value = var.get_value(); // extracts the value by reference + * \endcode + * + * \remark Only call this method when it is possible to return the containing value as the given type \p T. + * Use therefore the method \ref is_type(). + * Otherwise the call leads to undefined behaviour. + * Also make sure you don't clean this variant, when you still hold a reference to the containing value. + * + * \see is_type() + * + * \return A reference to the stored value. + */ + template + T& get_value(); + /*! * \brief Returns a reference to the containing value as type \p T. * @@ -1067,6 +1098,9 @@ class RTTR_API variant friend struct detail::variant_data_base_policy; friend struct detail::variant_data_policy_nullptr_t; friend RTTR_API bool detail::variant_compare_less(const variant&, const type&, const variant&, const type&, bool& ok); + template + friend RTTR_INLINE T* detail::unsafe_variant_cast(variant* operand) RTTR_NOEXCEPT; + detail::variant_data m_data; detail::variant_policy_func m_policy; @@ -1074,6 +1108,97 @@ class RTTR_API variant ///////////////////////////////////////////////////////////////////////////////////////// +/*! + * \brief Returns a reference to the containing value as type \p T. + * + * \code{.cpp} + * + * variant var = std::string("hello world"); + * std:string& value_ref = variant_cast(var); // extracts the value by reference + * std:string value = variant_cast(var); // copies the value + * + * \endcode + * + * \remark Extracting a value type, which is not stored in the variant, leads to undefined behaviour. + * No exception or error code will be returned! + */ +template +T variant_cast(const variant& operand); + +/*! + * \brief Returns a reference to the containing value as type \p T. + * + * \code{.cpp} + * + * variant var = std::string("hello world"); + * std:string& value_ref = variant_cast(var); // extracts the value by reference + * std:string value = variant_cast(var); // copies the value + * + * \endcode + * + * \remark Extracting a value type, which is not stored in the variant, leads to undefined behaviour. + * No exception or error code will be returned! + */ +template +T variant_cast(variant& operand); + +/*! + * \brief Move the containing value from the variant into a type \p T. + * + * \code{.cpp} + * + * variant var = std::string("hello world"); + * std::string& a = variant_cast(var); + * std:string b = variant_cast(std::move(var)); // move the value to 'b' + * std::cout << "a: " << a << std::endl; // is now empty + * std::cout << "b: " << b << std::endl; // prints "hello world" + * + * \endcode + * + * \remark Extracting a value type, which is not stored in the variant, leads to undefined behaviour. + * No exception or error code will be returned! + */ +template +T variant_cast(variant&& operand); + +/*! + * \brief Returns a pointer to the containing value with type \p T. + * When the containing value is of type \p T, a valid pointer to the type will be returned. + * Otherwise a `nullptr` is returned. + * + * \code{.cpp} + * + * variant var = std::string("hello world"); + * std:string* a = variant_cast(&var); // performs an internal type check and returns extracts the value by reference + * int* b = variant_cast(&var); + * std::cout << "a valid: " << a != nullptr << std::endl; + * std::cout << "b valid: " << b != nullptr << std::endl; + * \endcode + * + * \return A valid pointer, when the containing type is of type \p T; otherwise a `nullptr`. + */ +template +const T* variant_cast(const variant* operand) RTTR_NOEXCEPT; + +/*! + * \brief Returns a pointer to the containing value with type \p T. + * When the containing value is of type \p T, a valid pointer to the type will be returned. + * Otherwise a `nullptr` is returned. + * + * \code{.cpp} + * + * variant var = std::string("hello world"); + * std:string* a = variant_cast(&var); // performs an internal type check and returns extracts the value by reference + * int* b = variant_cast(&var); + * std::cout << "a valid: " << a != nullptr << std::endl; + * std::cout << "b valid: " << b != nullptr << std::endl; + * \endcode + * + * \return A valid pointer, when the containing type is of type \p T; otherwise a `nullptr`. + */ +template +T* variant_cast(variant* operand) RTTR_NOEXCEPT; + } // end namespace rttr #include "rttr/detail/variant/variant_impl.h" diff --git a/src/unit_tests/unit_tests.cmake b/src/unit_tests/unit_tests.cmake index 78e51381..92fbf8ac 100644 --- a/src/unit_tests/unit_tests.cmake +++ b/src/unit_tests/unit_tests.cmake @@ -78,6 +78,7 @@ set(SOURCE_FILES main.cpp variant/variant_cmp_less_or_equal.cpp variant/variant_cmp_greater_or_equal.cpp variant/variant_misc_test.cpp + variant/variant_cast_test.cpp variant/variant_conv_to_bool.cpp variant/variant_conv_to_int8.cpp variant/variant_conv_to_int16.cpp diff --git a/src/unit_tests/variant/variant_cast_test.cpp b/src/unit_tests/variant/variant_cast_test.cpp new file mode 100644 index 00000000..a087533d --- /dev/null +++ b/src/unit_tests/variant/variant_cast_test.cpp @@ -0,0 +1,232 @@ +/************************************************************************************ +* * +* Copyright (c) 2014, 2015 - 2017 Axel Menzel * +* * +* This file is part of RTTR (Run Time Type Reflection) * +* License: MIT License * +* * +* Permission is hereby granted, free of charge, to any person obtaining * +* a copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * +* SOFTWARE. * +* * +*************************************************************************************/ + +#include +#include +#include + +using namespace rttr; + + +///////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("variant - variant_cast(variant*)", "[variant]") +{ + SECTION("empty cast") + { + variant var; + + auto value = variant_cast(&var); + + CHECK(value == nullptr); + } + + SECTION("valid cast") + { + variant var = 12; + + auto value = variant_cast(&var); + + CHECK(value != nullptr); + + using value_t = std::remove_reference_t; + static_assert(std::is_same::value, "Must be integer pointer type!"); + + REQUIRE(value != nullptr); + CHECK(*value == 12); + } + + SECTION("invalid cast") + { + variant var = 12; + + auto value = variant_cast(&var); + CHECK(value == nullptr); // nullptr, because not of type "int" + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("variant - variant_cast(const variant*)", "[variant]") +{ + SECTION("empty cast") + { + const variant var; + + auto value = variant_cast(&var); + + CHECK(value == nullptr); + } + + SECTION("valid cast") + { + const variant var = 12; + + auto value = variant_cast(&var); + + CHECK(value != nullptr); + + using value_t = std::remove_reference_t; + static_assert(std::is_same::value, "Must be integer pointer type!"); + + REQUIRE(value != nullptr); + CHECK(*value == 12); + } + + SECTION("invalid cast") + { + const variant var = 12; + + auto value = variant_cast(&var); + CHECK(value == nullptr); // nullptr, because not of type "int" + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("variant - variant_cast(variant&)", "[variant]") +{ + SECTION("by value") + { + variant var = 12; + + REQUIRE(var.get_type() == type::get()); + + auto value = variant_cast(var); + CHECK(value == 12); + using value_t = decltype(value); + static_assert(!std::is_reference::value, "Must be value type!"); + } + + SECTION("by reference") + { + variant var = 12; + + REQUIRE(var.get_type() == type::get()); + + auto& value = variant_cast(var); + CHECK(value == 12); + + using value_t = decltype(value); + static_assert(std::is_reference::value, "Must be reference type!"); + } + + SECTION("move from") + { + std::string text = "cat"; + variant var = text; + + REQUIRE(var.get_type() == type::get()); + + std::string s; + s = std::move(variant_cast(var)); + CHECK(s == text); + CHECK(variant_cast(var).empty() == true); + + std::string text2 = "hello"; + variant_cast(var) = std::move(text2); + CHECK(variant_cast(var) == "hello"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("variant - variant_cast(const variant&)", "[variant]") +{ + SECTION("by value") + { + const variant var = 12; + + CHECK(var.get_type() == type::get()); + + auto value = variant_cast(var); + CHECK(value == 12); + using value_t = decltype(value); + static_assert(!std::is_reference::value, "Must be value type!"); + } + + SECTION("by reference") + { + std::string text = "cat"; + const variant var = text; + + CHECK(var.get_type() == type::get()); + + auto& value = variant_cast(var); + CHECK(value == text); + + using value_t = decltype(value); + static_assert(std::is_reference::value, "Must be reference type!"); + static_assert(std::is_const>::value, "Must be const-reference type!"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int move_count = 0; + +struct moveable_class + { + moveable_class(moveable_class&&) + { + ++move_count; + } + moveable_class() {} + moveable_class(const moveable_class&) {} + int value = 12; +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("variant - variant_cast(variant&&)", "[variant]") +{ + SECTION("move test - string") + { + std::string text = "cat"; + variant var = text; + + CHECK(var.get_type() == type::get()); + + auto value = variant_cast(std::move(var)); + CHECK(value == text); + } + + SECTION("move test") + { + moveable_class obj; + variant var = std::move(obj); + CHECK(move_count == 1); + moveable_class m2 = variant_cast(std::move(var)); + CHECK(move_count == 2); + + moveable_class&& m3 = variant_cast(std::move(var)); + CHECK(move_count == 3); + CHECK(m3.value == 12); // to avoid not used variable warning + } +} + +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/unit_tests/variant/variant_misc_test.cpp b/src/unit_tests/variant/variant_misc_test.cpp index 2b2eabce..5d997181 100644 --- a/src/unit_tests/variant/variant_misc_test.cpp +++ b/src/unit_tests/variant/variant_misc_test.cpp @@ -101,6 +101,36 @@ TEST_CASE("variant - swap", "[variant]") ///////////////////////////////////////////////////////////////////////////////////////// +TEST_CASE("variant - get_value()", "[variant]") +{ + SECTION("check get_value() non-const version") + { + std::string text = "hello world"; + variant var = text; + + auto& value = var.get_value(); + value = "world"; + using value_t = std::remove_reference_t; + + static_assert(!std::is_const::value, "Provide non-const getter!"); + + CHECK(var.get_value() == "world"); + } + + SECTION("check get_value() const version") + { + std::string text = "hello world"; + const variant var = text; + + auto& value = var.get_value(); + + using value_t = std::remove_reference_t; + static_assert(std::is_const::value, "Provide non-const getter!"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + TEST_CASE("variant - get_wrapped_value", "[variant]") { int foo = 12; From 9bd0a220f00b7546c606ac00a29f222a3d51dbbe Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Mon, 5 Mar 2018 23:49:31 +0100 Subject: [PATCH 2/8] added pointer-pointer test to variant_cast and fixed moveable test --- src/unit_tests/variant/variant_cast_test.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/unit_tests/variant/variant_cast_test.cpp b/src/unit_tests/variant/variant_cast_test.cpp index a087533d..540814c1 100644 --- a/src/unit_tests/variant/variant_cast_test.cpp +++ b/src/unit_tests/variant/variant_cast_test.cpp @@ -60,6 +60,16 @@ TEST_CASE("variant - variant_cast(variant*)", "[variant]") CHECK(*value == 12); } + SECTION("valid cast - pointer") + { + int obj = 12; + variant var = &obj; + + auto value = variant_cast(&var); + REQUIRE(value != nullptr); + CHECK(**value == 12); + } + SECTION("invalid cast") { variant var = 12; @@ -224,7 +234,7 @@ TEST_CASE("variant - variant_cast(variant&&)", "[variant]") CHECK(move_count == 2); moveable_class&& m3 = variant_cast(std::move(var)); - CHECK(move_count == 3); + CHECK(move_count == 2); // will not move CHECK(m3.value == 12); // to avoid not used variable warning } } From 0ed9d747a24fe6bdb15f2234497c2e0cb66522bb Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Tue, 6 Mar 2018 00:07:15 +0100 Subject: [PATCH 3/8] fixed compile error, because of not defined: std::add_lvalue_reference_t in C++11 --- src/rttr/detail/misc/std_type_traits.h | 3 +++ src/rttr/detail/variant/variant_impl.h | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rttr/detail/misc/std_type_traits.h b/src/rttr/detail/misc/std_type_traits.h index e48544ca..49f28549 100644 --- a/src/rttr/detail/misc/std_type_traits.h +++ b/src/rttr/detail/misc/std_type_traits.h @@ -248,6 +248,9 @@ using decay_t = typename std::decay::type; template using add_const_t = typename std::add_const::type; +template +using add_lvalue_reference_t = typename std::add_lvalue_reference::type; + ///////////////////////////////////////////////////////////////////////////////////// } // end namespace detail diff --git a/src/rttr/detail/variant/variant_impl.h b/src/rttr/detail/variant/variant_impl.h index f56c591b..e98b5460 100644 --- a/src/rttr/detail/variant/variant_impl.h +++ b/src/rttr/detail/variant/variant_impl.h @@ -141,7 +141,7 @@ RTTR_INLINE T& variant::get_value() using namespace detail; auto result = unsafe_variant_cast>(this); - using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return *result; } @@ -153,7 +153,7 @@ RTTR_INLINE const T& variant::get_value() const using namespace detail; auto result = unsafe_variant_cast>(this); - using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return *result; } @@ -446,7 +446,7 @@ RTTR_INLINE T variant_cast(const variant& operand) auto result = unsafe_variant_cast>(&operand); - using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return static_cast(*result); } @@ -461,7 +461,7 @@ RTTR_INLINE T variant_cast(variant& operand) auto result = unsafe_variant_cast>(&operand); - using ref_type = conditional_t::value, T, std::add_lvalue_reference_t>; + using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return static_cast(*result); } From 8f9d65dc19a53a4e829b222210e7675cecc2fdc2 Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Tue, 6 Mar 2018 00:24:33 +0100 Subject: [PATCH 4/8] remove not used typedef --- src/rttr/detail/variant/variant_impl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rttr/detail/variant/variant_impl.h b/src/rttr/detail/variant/variant_impl.h index e98b5460..79a430b6 100644 --- a/src/rttr/detail/variant/variant_impl.h +++ b/src/rttr/detail/variant/variant_impl.h @@ -141,7 +141,6 @@ RTTR_INLINE T& variant::get_value() using namespace detail; auto result = unsafe_variant_cast>(this); - using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return *result; } @@ -153,7 +152,6 @@ RTTR_INLINE const T& variant::get_value() const using namespace detail; auto result = unsafe_variant_cast>(this); - using ref_type = conditional_t::value, T, add_lvalue_reference_t>; return *result; } From b14bcfe1ded8cd899a0fb317fed217ae3a0e6d05 Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Tue, 6 Mar 2018 00:43:36 +0100 Subject: [PATCH 5/8] fixed usage of c++14 type_trait --- src/rttr/detail/variant/variant_impl.h | 2 +- src/unit_tests/variant/variant_cast_test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rttr/detail/variant/variant_impl.h b/src/rttr/detail/variant/variant_impl.h index 79a430b6..d65882c9 100644 --- a/src/rttr/detail/variant/variant_impl.h +++ b/src/rttr/detail/variant/variant_impl.h @@ -43,7 +43,7 @@ namespace rttr namespace detail { template -using variant_t = detail::remove_cv_t>; +using variant_t = remove_cv_t>; } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/unit_tests/variant/variant_cast_test.cpp b/src/unit_tests/variant/variant_cast_test.cpp index 540814c1..cf17d005 100644 --- a/src/unit_tests/variant/variant_cast_test.cpp +++ b/src/unit_tests/variant/variant_cast_test.cpp @@ -53,7 +53,7 @@ TEST_CASE("variant - variant_cast(variant*)", "[variant]") CHECK(value != nullptr); - using value_t = std::remove_reference_t; + using value_t = detail::remove_reference_t; static_assert(std::is_same::value, "Must be integer pointer type!"); REQUIRE(value != nullptr); @@ -100,7 +100,7 @@ TEST_CASE("variant - variant_cast(const variant*)", "[variant]") CHECK(value != nullptr); - using value_t = std::remove_reference_t; + using value_t = detail::remove_reference_t; static_assert(std::is_same::value, "Must be integer pointer type!"); REQUIRE(value != nullptr); From 7785fe535e87b3c4ea3a22ff7faeb3c983128d33 Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Tue, 6 Mar 2018 01:03:45 +0100 Subject: [PATCH 6/8] removed ununused typedef's --- src/unit_tests/variant/variant_cast_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/unit_tests/variant/variant_cast_test.cpp b/src/unit_tests/variant/variant_cast_test.cpp index cf17d005..0afdd667 100644 --- a/src/unit_tests/variant/variant_cast_test.cpp +++ b/src/unit_tests/variant/variant_cast_test.cpp @@ -53,7 +53,6 @@ TEST_CASE("variant - variant_cast(variant*)", "[variant]") CHECK(value != nullptr); - using value_t = detail::remove_reference_t; static_assert(std::is_same::value, "Must be integer pointer type!"); REQUIRE(value != nullptr); @@ -100,7 +99,6 @@ TEST_CASE("variant - variant_cast(const variant*)", "[variant]") CHECK(value != nullptr); - using value_t = detail::remove_reference_t; static_assert(std::is_same::value, "Must be integer pointer type!"); REQUIRE(value != nullptr); @@ -232,6 +230,7 @@ TEST_CASE("variant - variant_cast(variant&&)", "[variant]") CHECK(move_count == 1); moveable_class m2 = variant_cast(std::move(var)); CHECK(move_count == 2); + CHECK(m2.value == 12); // to avoid not used variable warning moveable_class&& m3 = variant_cast(std::move(var)); CHECK(move_count == 2); // will not move From 55ffd5392ff952011b6d01544dd089f99fc8b47d Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Tue, 6 Mar 2018 09:10:07 +0100 Subject: [PATCH 7/8] fixed unit tests --- src/unit_tests/variant/variant_misc_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/unit_tests/variant/variant_misc_test.cpp b/src/unit_tests/variant/variant_misc_test.cpp index 5d997181..627c57aa 100644 --- a/src/unit_tests/variant/variant_misc_test.cpp +++ b/src/unit_tests/variant/variant_misc_test.cpp @@ -110,7 +110,7 @@ TEST_CASE("variant - get_value()", "[variant]") auto& value = var.get_value(); value = "world"; - using value_t = std::remove_reference_t; + using value_t = detail::remove_reference_t; static_assert(!std::is_const::value, "Provide non-const getter!"); @@ -124,8 +124,9 @@ TEST_CASE("variant - get_value()", "[variant]") auto& value = var.get_value(); - using value_t = std::remove_reference_t; + using value_t = detail::remove_reference_t; static_assert(std::is_const::value, "Provide non-const getter!"); + CHECK(value == text); } } From 6a9fb303587f044ff2b627608d00091d67a729fa Mon Sep 17 00:00:00 2001 From: Axel Menzel Date: Thu, 8 Mar 2018 19:41:12 +0100 Subject: [PATCH 8/8] adjusted grammar in code example of "variant_cast" --- src/rttr/variant.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rttr/variant.h b/src/rttr/variant.h index f2ce9d21..51292aab 100644 --- a/src/rttr/variant.h +++ b/src/rttr/variant.h @@ -1150,7 +1150,7 @@ T variant_cast(variant& operand); * variant var = std::string("hello world"); * std::string& a = variant_cast(var); * std:string b = variant_cast(std::move(var)); // move the value to 'b' - * std::cout << "a: " << a << std::endl; // is now empty + * std::cout << "a: " << a << std::endl; // is now empty (nothing to print) * std::cout << "b: " << b << std::endl; // prints "hello world" * * \endcode @@ -1169,10 +1169,10 @@ T variant_cast(variant&& operand); * \code{.cpp} * * variant var = std::string("hello world"); - * std:string* a = variant_cast(&var); // performs an internal type check and returns extracts the value by reference + * std:string* a = variant_cast(&var); // performs an internal type check and returns the value by reference * int* b = variant_cast(&var); - * std::cout << "a valid: " << a != nullptr << std::endl; - * std::cout << "b valid: " << b != nullptr << std::endl; + * std::cout << "a valid: " << a != nullptr << std::endl; // prints "1" + * std::cout << "b valid: " << b != nullptr << std::endl; // prints "0" * \endcode * * \return A valid pointer, when the containing type is of type \p T; otherwise a `nullptr`. @@ -1188,10 +1188,10 @@ const T* variant_cast(const variant* operand) RTTR_NOEXCEPT; * \code{.cpp} * * variant var = std::string("hello world"); - * std:string* a = variant_cast(&var); // performs an internal type check and returns extracts the value by reference + * std:string* a = variant_cast(&var); // performs an internal type check and returns the value by reference * int* b = variant_cast(&var); - * std::cout << "a valid: " << a != nullptr << std::endl; - * std::cout << "b valid: " << b != nullptr << std::endl; + * std::cout << "a valid: " << a != nullptr << std::endl; // prints "1" + * std::cout << "b valid: " << b != nullptr << std::endl; // prints "0" * \endcode * * \return A valid pointer, when the containing type is of type \p T; otherwise a `nullptr`.