diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 985cf43..1c48908 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -10,6 +10,8 @@ jobs: matrix: config: # https://github.com/actions/virtual-environments/tree/main/images/win + - { os: "windows-2016", vs: "Visual Studio 2017", arch: "x86" } + - { os: "windows-2016", vs: "Visual Studio 2017", arch: "x64" } - { os: "windows-2019", vs: "Visual Studio 2019", arch: "x86" } - { os: "windows-2019", vs: "Visual Studio 2019", arch: "x64" } name: "${{matrix.config.vs}} ${{matrix.config.arch}}" diff --git a/README.md b/README.md index c02fbbe..28a7de1 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ - [gcc](https://www.gnu.org/software/gcc/) **>= 7** - [clang](https://clang.llvm.org/) **>= 7** -- [msvc](https://visualstudio.microsoft.com/) **>= 2019** +- [msvc](https://visualstudio.microsoft.com/) **>= 2017** ## Installation diff --git a/headers/meta.hpp/meta_value.hpp b/headers/meta.hpp/meta_value.hpp index f353e71..12737f2 100644 --- a/headers/meta.hpp/meta_value.hpp +++ b/headers/meta.hpp/meta_value.hpp @@ -18,8 +18,7 @@ namespace meta_hpp::value_detail struct traits { void*(*data)(value&); const void*(*cdata)(const value&); - bool(*equal)(const value&, const value&){}; - bool(*not_equal)(const value&, const value&){}; + bool(*equals)(const value&, const value&){}; }; template < typename T > @@ -29,18 +28,14 @@ namespace meta_hpp::value_detail const void* value_cdata(const value& v); template < typename T > - bool value_equal(const value& l, const value& r); - - template < typename T > - bool value_not_equal(const value& l, const value& r); + bool value_equals(const value& l, const value& r); template < typename T > const traits* get_traits() noexcept { static traits traits{ &value_data, &value_cdata, - &value_equal, - &value_not_equal, + &value_equals, }; return &traits; } @@ -136,46 +131,14 @@ namespace meta_hpp template < typename T , typename U = std::decay_t - , typename = std::enable_if_t> - , typename = std::enable_if_t, U, U>> > - friend bool operator==(const value& l, T&& r) { - return l.fid() == get_family_id() - && std::equal_to<>{}(*l.try_cast(), std::forward(r)); + , typename = std::enable_if_t> > + bool equals(T&& other) const { + return fid() == get_family_id() + && std::equal_to<>{}(*try_cast(), std::forward(other)); } - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> - , typename = std::enable_if_t, U, U>> > - friend bool operator==(T&& l, const value& r) { - return get_family_id() == r.fid() - && std::equal_to<>{}(std::forward(l), *r.try_cast()); - } - - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> - , typename = std::enable_if_t, U, U>> > - friend bool operator!=(const value& l, T&& r) { - return l.fid() != get_family_id() - || std::not_equal_to<>{}(*l.try_cast(), std::forward(r)); - } - - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> - , typename = std::enable_if_t, U, U>> > - friend bool operator!=(T&& l, const value& r) { - return get_family_id() != r.fid() - || std::not_equal_to<>{}(std::forward(l), *r.try_cast()); - } - - friend bool operator==(const value& l, const value& r) { - return l.traits_->equal(l, r); - } - - friend bool operator!=(const value& l, const value& r) { - return l.traits_->not_equal(l, r); + bool equals(const value& other) const { + return traits_->equals(*this, other); } public: bool to_bool() const { return cast(); } @@ -225,14 +188,6 @@ namespace meta_hpp const value_detail::traits* traits_{}; }; - inline void* data(value& v) noexcept { - return v.data(); - } - - inline const void* data(const value& v) noexcept { - return v.data(); - } - inline void swap(value& l, value& r) noexcept { l.swap(r); } @@ -251,26 +206,14 @@ namespace meta_hpp::value_detail } template < typename T > - bool value_equal(const value& l, const value& r) { + bool value_equals(const value& l, const value& r) { if ( l.fid() != r.fid() ) { return false; } if constexpr ( std::is_invocable_v, T, T> ) { - return std::equal_to<>{}(*l.try_cast(), *(r.try_cast())); + return std::equal_to<>{}(*l.try_cast(), *r.try_cast()); } else { return std::addressof(l) == std::addressof(r); } } - - template < typename T > - bool value_not_equal(const value& l, const value& r) { - if ( l.fid() != r.fid() ) { - return true; - } - if constexpr ( std::is_invocable_v, T, T> ) { - return std::not_equal_to<>{}(*l.try_cast(), *(r.try_cast())); - } else { - return std::addressof(l) != std::addressof(r); - } - } } diff --git a/untests/meta_value_tests.cpp b/untests/meta_value_tests.cpp index e866ea7..9231483 100644 --- a/untests/meta_value_tests.cpp +++ b/untests/meta_value_tests.cpp @@ -106,86 +106,55 @@ TEST_CASE("meta/value/equal") { using namespace std::string_literals; { - CHECK(meta::value{1} == 1); - CHECK(meta::value{1} != 0); - CHECK(meta::value{1} != "hello"s); - - CHECK_FALSE(meta::value{1} != 1); - CHECK_FALSE(meta::value{1} == 0); - CHECK_FALSE(meta::value{1} == "hello"s); - } - - { - CHECK(1 == meta::value{1}); - CHECK(0 != meta::value{1}); - CHECK("hello"s != meta::value{1}); - - CHECK_FALSE(1 != meta::value{1}); - CHECK_FALSE(0 == meta::value{1}); - CHECK_FALSE("hello"s == meta::value{1}); + CHECK(meta::value{1}.equals(1)); + CHECK_FALSE(meta::value{1}.equals(0)); + CHECK_FALSE(meta::value{1}.equals("hello"s)); } { int i = 1; - CHECK(meta::value{1} == i); - CHECK(meta::value{1} == std::as_const(i)); - CHECK_FALSE(meta::value{1} != i); - CHECK_FALSE(meta::value{1} != std::as_const(i)); - - CHECK(i == meta::value{1}); - CHECK(std::as_const(i) == meta::value{1}); - CHECK_FALSE(i != meta::value{1}); - CHECK_FALSE(std::as_const(i) != meta::value{1}); + CHECK(meta::value{1}.equals(i)); + CHECK(meta::value{1}.equals(std::as_const(i))); + CHECK_FALSE(meta::value{2}.equals(i)); + CHECK_FALSE(meta::value{2}.equals(std::as_const(i))); } { - CHECK(meta::value{1} == meta::value{1}); - CHECK(meta::value{1} != meta::value{0}); - CHECK(meta::value{1} != meta::value{"hello"s}); - CHECK_FALSE(meta::value{1} != meta::value{1}); - CHECK_FALSE(meta::value{1} == meta::value{0}); - CHECK_FALSE(meta::value{1} == meta::value{"hello"s}); + CHECK(meta::value{1}.equals(meta::value{1})); + CHECK_FALSE(meta::value{1}.equals(meta::value{0})); + CHECK_FALSE(meta::value{1}.equals(meta::value{"hello"s})); - CHECK(meta::value{1} == meta::value{1}); - CHECK(meta::value{0} != meta::value{1}); - CHECK(meta::value{"hello"s} != meta::value{1}); - CHECK_FALSE(meta::value{1} != meta::value{1}); - CHECK_FALSE(meta::value{0} == meta::value{1}); - CHECK_FALSE(meta::value{"hello"s} == meta::value{1}); + CHECK(meta::value{1}.equals(meta::value{1})); + CHECK_FALSE(meta::value{0}.equals(meta::value{1})); + CHECK_FALSE(meta::value{"hello"s}.equals(meta::value{1})); } { - CHECK(meta::value{std::in_place_type, 1} == meta::value{1}); - CHECK(meta::value{1} == meta::value{std::in_place_type, 1}); + CHECK(meta::value{std::in_place_type, 1}.equals(meta::value{1})); + CHECK(meta::value{1}.equals(meta::value{std::in_place_type, 1})); using vi = std::vector; - CHECK(meta::value{std::in_place_type, {1,2,3}} == meta::value{vi{1,2,3}}); - CHECK(meta::value{vi{1,2,3}} == meta::value{std::in_place_type, {1,2,3}}); - CHECK_FALSE(meta::value{std::in_place_type, {1,2,3}} == meta::value{vi{1,2,4}}); - CHECK_FALSE(meta::value{vi{1,2,4}} == meta::value{std::in_place_type, {1,2,3}}); + CHECK(meta::value{std::in_place_type, {1,2,3}}.equals(meta::value{vi{1,2,3}})); + CHECK(meta::value{vi{1,2,3}}.equals(meta::value{std::in_place_type, {1,2,3}})); + CHECK_FALSE(meta::value{std::in_place_type, {1,2,3}}.equals(meta::value{vi{1,2,4}})); + CHECK_FALSE(meta::value{vi{1,2,4}}.equals(meta::value{std::in_place_type, {1,2,3}})); } { meta::value v1{&func}; meta::value v2{&func}; - CHECK(v1 == v1); - CHECK_FALSE(v1 != v1); - - CHECK(v1 == v2); - CHECK_FALSE(v1 != v2); + CHECK(v1.equals(v1)); + CHECK(v1.equals(v2)); } { meta::value v1{clazz{}}; meta::value v2{clazz{}}; - CHECK(v1 == v1); - CHECK_FALSE(v1 != v1); - - CHECK(v1 != v2); - CHECK_FALSE(v1 == v2); + CHECK(v1.equals(v1)); + CHECK_FALSE(v1.equals(v2)); } { @@ -194,14 +163,13 @@ TEST_CASE("meta/value/equal") { meta::value v1{&rv}; meta::value v2{&rv}; - CHECK(v1 == v1); - CHECK_FALSE(v1 != v1); + CHECK(v1.equals(v1)); } { meta::value v1{"hello"s}; meta::value{1}.swap(v1); - CHECK(v1 == meta::value{1}); + CHECK(v1.equals(meta::value{1})); } }