From 214cb3b0cd8226e1440e37dff97a3426f5ecdc4b Mon Sep 17 00:00:00 2001 From: Tony Riviere Date: Tue, 22 Mar 2022 12:46:42 +0100 Subject: [PATCH] variant constructor and assignment shouldn't allow narrow conversion to respect standard specification --- include/EASTL/meta.h | 20 +++++++++++++------- test/source/TestMeta.cpp | 2 +- test/source/TestVariant.cpp | 12 ++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/include/EASTL/meta.h b/include/EASTL/meta.h index 545354d4..69b220d7 100644 --- a/include/EASTL/meta.h +++ b/include/EASTL/meta.h @@ -181,17 +181,21 @@ namespace eastl // overload_resolution has selected a function to run. // + // Helper used to check for valid conversions that don't involve narrowing. + template + T make_overload_array(T(&&)[1]); + // a single overload of an individual type template struct overload { - // Overload is implicitly convertible to the surrogated function - // call for pointer to member functions (pmf). This gets around - // variadic pack expansion in a class using statement being a C++17 - // language feature. It is the core mechanism of aggregating all the + // Overload is a functor that will be selected by overload resolution + // if and only if there's no narrow conversion to convert ParamType into T. + // This gets around variadic pack expansion in a class using statement being + // a C++17 language feature. It is the core mechanism of aggregating all the // individual overloads into the overload_set structure. - using F = T (*)(T); - operator F() const { return nullptr; } + template ({declval()}))> + T operator()(T, ParamType&&); }; template struct overload_set_impl; @@ -206,7 +210,9 @@ namespace eastl }; EA_DISABLE_VC_WARNING(4242 4244) // conversion from 'T' to 'U', possible loss of data. - template ()(declval()))> + template ()(declval(), declval()))> struct overload_resolution { // capture the return type of the function the compiler selected by diff --git a/test/source/TestMeta.cpp b/test/source/TestMeta.cpp index 8d2e9d1e..eda7060f 100644 --- a/test/source/TestMeta.cpp +++ b/test/source/TestMeta.cpp @@ -80,12 +80,12 @@ int TestOverloadResolution() int nErrorCount = 0; static_assert(is_same_v>, int>, "error"); - static_assert(is_same_v>, short>, "error"); static_assert(is_same_v>, long>, "error"); static_assert(is_same_v>, int>, "error"); static_assert(is_same_v>, int>, "error"); static_assert(is_same_v>, int>, "error"); static_assert(is_same_v>, int>, "error"); + static_assert(is_same_v>, int>, "error"); static_assert(is_same_v>, int>, "error"); static_assert(is_same_v>, int>, "error"); diff --git a/test/source/TestVariant.cpp b/test/source/TestVariant.cpp index a8197e50..d2e83c71 100644 --- a/test/source/TestVariant.cpp +++ b/test/source/TestVariant.cpp @@ -205,6 +205,18 @@ int TestVariantBasic() VERIFY(*(get_if(&v)) == "a"); } + { + // verify construction where only one candidate doesn't require narrow conversion + variant v = 42; + VERIFY(holds_alternative(v)); + VERIFY(get(v) == 42); + + // and assignment operator= + v = 43; + VERIFY(holds_alternative(v)); + VERIFY(get(v) == 43); + } + return nErrorCount; }