From 93ddae5336bbf49aa72d7dd7f7f8865250c7e7e2 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 16 Feb 2025 18:46:08 +0100 Subject: [PATCH 1/7] Add additional type deduction guides for indirect --- feature_check.h | 14 ++++++++++++++ indirect.h | 11 ++++++++--- indirect_test.cc | 38 ++++++++++++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/feature_check.h b/feature_check.h index 429f0adc..504a5ece 100644 --- a/feature_check.h +++ b/feature_check.h @@ -95,4 +95,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif //(__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= // 202002L) +// +// XYZ_HAS_STD_TYPE_IDENTITY +// The macro is defined when std::type_identity_t is available. +// + +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +#error "XYZ_HAS_STD_TYPE_IDENTITY is already defined" +#endif // XYZ_HAS_STD_TYPE_IDENTITY + +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define XYZ_HAS_STD_TYPE_IDENTITY +#endif //(__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= +// 202002L) + #endif // XYZ_FEATURE_CHECK_H diff --git a/indirect.h b/indirect.h index 7869cc4c..a8c2988c 100644 --- a/indirect.h +++ b/indirect.h @@ -182,7 +182,7 @@ class indirect { p_ = construct_from(alloc_, ilist, std::forward(us)...); } - constexpr indirect(std::allocator_arg_t, const A& alloc, + constexpr indirect(std::allocator_arg_t, const std::type_identity_t& alloc, const indirect& other) : alloc_(alloc) { static_assert(std::copy_constructible); @@ -195,7 +195,7 @@ class indirect { } constexpr indirect( - std::allocator_arg_t, const A& alloc, + std::allocator_arg_t, const std::type_identity_t& alloc, indirect&& other) noexcept(allocator_traits::is_always_equal::value) : p_(nullptr), alloc_(alloc) { static_assert(std::move_constructible); @@ -465,10 +465,15 @@ concept is_hashable = requires(T t) { std::hash{}(t); }; template indirect(Value) -> indirect; -template +template , int> = 0> indirect(std::allocator_arg_t, Alloc, Value) -> indirect< Value, typename std::allocator_traits::template rebind_alloc>; +template +indirect(std::allocator_arg_t, std::type_identity_t, + indirect) -> indirect; + } // namespace xyz template diff --git a/indirect_test.cc b/indirect_test.cc index 9d9b99d3..6174b6e7 100644 --- a/indirect_test.cc +++ b/indirect_test.cc @@ -120,14 +120,44 @@ TEST(IndirectTest, AllocatorExtendedInitializerListConstructor) { #ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION TEST(IndirectTest, TemplateArgumentDeduction) { - xyz::indirect a(42); - EXPECT_EQ(*a, 42); + xyz::indirect i(42); + EXPECT_EQ(*i, 42); +} + +TEST(IndirectTest, TemplateArgumentDeductionCopy) { + xyz::indirect i(42); + xyz::indirect ii(i); + + static_assert(std::is_same_v); + EXPECT_EQ(*ii, 42); } TEST(IndirectTest, TemplateArgumentDeductionWithAllocator) { - xyz::indirect a(std::allocator_arg, std::allocator{}, 42); - EXPECT_EQ(*a, 42); + xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); + + static_assert( + std::is_same_v>); + EXPECT_EQ(*i, 42); +} + +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { + xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); + xyz::indirect ii(std::allocator_arg, 2, i); + + static_assert(std::is_same_v); + EXPECT_EQ(*ii, 42); + EXPECT_EQ(ii.get_allocator().tag, 2); +} + +TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { + xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); + xyz::indirect ii(std::allocator_arg, 2, std::move(i)); + EXPECT_EQ(*ii, 42); + EXPECT_EQ(ii.get_allocator().tag, 2); } +#endif // XYZ_HAS_STD_TYPE_IDENTITY #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION template > From 4bf19174e219c6a252d6856f3be2bbd433137b1d Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 16 Feb 2025 19:05:02 +0100 Subject: [PATCH 2/7] Add deduction guides for polymorphic --- .vscode/settings.json | 55 +++++++++++++++++++++++++++++++++++++++++++ polymorphic.h | 26 ++++++++++++++++++-- polymorphic_test.cc | 40 +++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e87f8eb9..9dc6c57f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,60 @@ ".venv": true, "bazel-*": true, "build": true, + }, + "files.associations": { + "__bit_reference": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__verbose_abort": "cpp", + "array": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "execution": "cpp", + "memory": "cpp", + "initializer_list": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "locale": "cpp", + "map": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "print": "cpp", + "queue": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "variant": "cpp", + "vector": "cpp", + "algorithm": "cpp" } } diff --git a/polymorphic.h b/polymorphic.h index 57cec8d3..153d2656 100644 --- a/polymorphic.h +++ b/polymorphic.h @@ -116,6 +116,15 @@ class direct_control_block final : public control_block { } // namespace detail +template +class polymorphic; + +template +inline constexpr bool is_polymorphic_v = false; + +template +inline constexpr bool is_polymorphic_v> = true; + template > class polymorphic { using cblock_t = detail::control_block; @@ -241,7 +250,8 @@ class polymorphic { cb_ = create_control_block(ilist, std::forward(ts)...); } - constexpr polymorphic(std::allocator_arg_t, const A& alloc, + constexpr polymorphic(std::allocator_arg_t, + const std::type_identity_t& alloc, const polymorphic& other) : alloc_(alloc) { if (!other.valueless_after_move()) { @@ -252,7 +262,7 @@ class polymorphic { } constexpr polymorphic( - std::allocator_arg_t, const A& alloc, + std::allocator_arg_t, const std::type_identity_t& alloc, polymorphic&& other) noexcept(allocator_traits::is_always_equal::value) : alloc_(alloc) { if constexpr (allocator_traits::is_always_equal::value) { @@ -405,6 +415,18 @@ class polymorphic { } }; +template +polymorphic(Value) -> polymorphic; + +template , int> = 0> +polymorphic(std::allocator_arg_t, Alloc, Value) -> polymorphic< + Value, typename std::allocator_traits::template rebind_alloc>; + +template +polymorphic(std::allocator_arg_t, std::type_identity_t, + polymorphic) -> polymorphic; + } // namespace xyz #endif // XYZ_POLYMORPHIC_H_ diff --git a/polymorphic_test.cc b/polymorphic_test.cc index 4d2c64d9..3ee6054b 100644 --- a/polymorphic_test.cc +++ b/polymorphic_test.cc @@ -845,4 +845,44 @@ TEST(PolymorphicTest, TaggedAllocatorsNotEqualMoveConstructFromValueless) { EXPECT_TRUE(iii.valueless_after_move()); } +TEST(PolymorphicTest, TemplateArgumentDeduction) { + xyz::polymorphic p(Derived(4)); + + EXPECT_EQ(p->value(), 4); +} + +TEST(PolymorphicTest, TemplateArgumentDeductionCopy) { + xyz::polymorphic p(Derived(4)); + xyz::polymorphic pp(p); + + static_assert(std::is_same_v); + + EXPECT_EQ(pp->value(), 4); +} + +TEST(PolymorphicTest, TemplateArgumentDeductionWithAllocator) { + xyz::TaggedAllocator a(1); + xyz::polymorphic p(std::allocator_arg, a, Derived(4)); + + EXPECT_EQ(p->value(), 4); + EXPECT_EQ(p.get_allocator().tag, 1); +} + +TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { + xyz::TaggedAllocator a(1); + xyz::polymorphic p(std::allocator_arg, a, Derived(4)); + xyz::polymorphic pp(std::allocator_arg, 2, p); + + EXPECT_EQ(pp->value(), 4); + EXPECT_EQ(pp.get_allocator().tag, 2); +} + +TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { + xyz::TaggedAllocator a(1); + xyz::polymorphic p(std::allocator_arg, a, Derived(4)); + xyz::polymorphic pp(std::allocator_arg, 2, std::move(p)); + + EXPECT_EQ(pp->value(), 4); + EXPECT_EQ(pp.get_allocator().tag, 2); +} } // namespace From 219756393e61b3ef135b86c9670b28aa9b8a71eb Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 16 Feb 2025 20:26:19 +0100 Subject: [PATCH 3/7] Add XYZ_HAS guards around deduction guide tests --- polymorphic_test.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/polymorphic_test.cc b/polymorphic_test.cc index 3ee6054b..54d5595f 100644 --- a/polymorphic_test.cc +++ b/polymorphic_test.cc @@ -845,6 +845,7 @@ TEST(PolymorphicTest, TaggedAllocatorsNotEqualMoveConstructFromValueless) { EXPECT_TRUE(iii.valueless_after_move()); } +#ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION TEST(PolymorphicTest, TemplateArgumentDeduction) { xyz::polymorphic p(Derived(4)); @@ -868,6 +869,7 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithAllocator) { EXPECT_EQ(p.get_allocator().tag, 1); } +#ifdef XYZ_HAS_STD_TYPE_IDENTITY TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { xyz::TaggedAllocator a(1); xyz::polymorphic p(std::allocator_arg, a, Derived(4)); @@ -885,4 +887,8 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { EXPECT_EQ(pp->value(), 4); EXPECT_EQ(pp.get_allocator().tag, 2); } + +#endif // XYZ_HAS_STD_TYPE_IDENTITY +#endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION + } // namespace From 389687bf53a4b1bf250b8d714efc46a2295c72a9 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 16 Feb 2025 20:41:24 +0000 Subject: [PATCH 4/7] Disable type-deduction tests for all but C++20 --- polymorphic_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polymorphic_test.cc b/polymorphic_test.cc index 54d5595f..c2675504 100644 --- a/polymorphic_test.cc +++ b/polymorphic_test.cc @@ -846,6 +846,7 @@ TEST(PolymorphicTest, TaggedAllocatorsNotEqualMoveConstructFromValueless) { } #ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION +#ifdef XYZ_HAS_STD_TYPE_IDENTITY TEST(PolymorphicTest, TemplateArgumentDeduction) { xyz::polymorphic p(Derived(4)); @@ -869,7 +870,6 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithAllocator) { EXPECT_EQ(p.get_allocator().tag, 1); } -#ifdef XYZ_HAS_STD_TYPE_IDENTITY TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { xyz::TaggedAllocator a(1); xyz::polymorphic p(std::allocator_arg, a, Derived(4)); From 3bc0f8befb5659805bbe8616db5b605dd44777d2 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 16 Feb 2025 22:31:06 +0000 Subject: [PATCH 5/7] Undo edit to settings.json --- .vscode/settings.json | 55 ------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9dc6c57f..e87f8eb9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,60 +4,5 @@ ".venv": true, "bazel-*": true, "build": true, - }, - "files.associations": { - "__bit_reference": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__node_handle": "cpp", - "__split_buffer": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__verbose_abort": "cpp", - "array": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "execution": "cpp", - "memory": "cpp", - "initializer_list": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "locale": "cpp", - "map": "cpp", - "mutex": "cpp", - "new": "cpp", - "optional": "cpp", - "ostream": "cpp", - "print": "cpp", - "queue": "cpp", - "ratio": "cpp", - "sstream": "cpp", - "stack": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "string": "cpp", - "string_view": "cpp", - "tuple": "cpp", - "typeinfo": "cpp", - "unordered_map": "cpp", - "variant": "cpp", - "vector": "cpp", - "algorithm": "cpp" } } From 39b26546e0b5847ca61a911947bbc1a2540dc63a Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Mon, 17 Feb 2025 07:52:40 +0000 Subject: [PATCH 6/7] Require a define to enable extended type deduction guides --- BUILD.bazel | 2 ++ CMakeLists.txt | 2 ++ indirect.h | 2 ++ indirect_test.cc | 2 ++ polymorphic.h | 4 ++-- polymorphic_test.cc | 2 ++ 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 9e4656de..bb5c22ff 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -13,6 +13,7 @@ cc_library( srcs = ["indirect.cc"], hdrs = ["indirect.h"], copts = ["-Iexternal/value_types/"], + defines = ["XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION"], visibility = ["//visibility:public"], deps = ["feature_check"], ) @@ -91,6 +92,7 @@ cc_library( srcs = ["polymorphic.cc"], hdrs = ["polymorphic.h"], copts = ["-Iexternal/value_types/"], + defines = ["XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION"], visibility = ["//visibility:public"], ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ea6f117..0e151aa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources(xyz_value_types xyz_add_library( NAME indirect ALIAS xyz_value_types::indirect + DEFINITIONS XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION ) target_sources(indirect INTERFACE @@ -75,6 +76,7 @@ target_sources(indirect_cxx17 xyz_add_library( NAME polymorphic ALIAS xyz_value_types::polymorphic + DEFINITIONS XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION ) target_sources(polymorphic INTERFACE diff --git a/indirect.h b/indirect.h index a8c2988c..09b5eba2 100644 --- a/indirect.h +++ b/indirect.h @@ -470,9 +470,11 @@ template indirect< Value, typename std::allocator_traits::template rebind_alloc>; +#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION template indirect(std::allocator_arg_t, std::type_identity_t, indirect) -> indirect; +#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION } // namespace xyz diff --git a/indirect_test.cc b/indirect_test.cc index 6174b6e7..f80b9570 100644 --- a/indirect_test.cc +++ b/indirect_test.cc @@ -141,6 +141,7 @@ TEST(IndirectTest, TemplateArgumentDeductionWithAllocator) { } #ifdef XYZ_HAS_STD_TYPE_IDENTITY +#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); xyz::indirect ii(std::allocator_arg, 2, i); @@ -157,6 +158,7 @@ TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { EXPECT_EQ(*ii, 42); EXPECT_EQ(ii.get_allocator().tag, 2); } +#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION #endif // XYZ_HAS_STD_TYPE_IDENTITY #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION diff --git a/polymorphic.h b/polymorphic.h index 153d2656..b27a6ca6 100644 --- a/polymorphic.h +++ b/polymorphic.h @@ -414,7 +414,7 @@ class polymorphic { } } }; - +#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION template polymorphic(Value) -> polymorphic; @@ -426,7 +426,7 @@ polymorphic(std::allocator_arg_t, Alloc, Value) -> polymorphic< template polymorphic(std::allocator_arg_t, std::type_identity_t, polymorphic) -> polymorphic; - +#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION } // namespace xyz #endif // XYZ_POLYMORPHIC_H_ diff --git a/polymorphic_test.cc b/polymorphic_test.cc index c2675504..e0b8c007 100644 --- a/polymorphic_test.cc +++ b/polymorphic_test.cc @@ -847,6 +847,7 @@ TEST(PolymorphicTest, TaggedAllocatorsNotEqualMoveConstructFromValueless) { #ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION #ifdef XYZ_HAS_STD_TYPE_IDENTITY +#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION TEST(PolymorphicTest, TemplateArgumentDeduction) { xyz::polymorphic p(Derived(4)); @@ -888,6 +889,7 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { EXPECT_EQ(pp.get_allocator().tag, 2); } +#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION #endif // XYZ_HAS_STD_TYPE_IDENTITY #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION From 4554ce710e6efaee088694ebd5d762d569840f0c Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Fri, 21 Feb 2025 12:13:55 -0500 Subject: [PATCH 7/7] Just testing --- BUILD.bazel | 6 ++++-- CMakeLists.txt | 2 -- indirect.h | 32 +++++++++++++++++++++----------- indirect_cxx14.h | 21 +++++++++++++++++++-- indirect_test.cc | 6 +----- polymorphic.h | 40 +++++++++++++++++++++++----------------- polymorphic_cxx14.h | 35 +++++++++++++++++++++++++++++++++-- polymorphic_test.cc | 10 +++------- 8 files changed, 104 insertions(+), 48 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index bb5c22ff..d698190e 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -13,7 +13,7 @@ cc_library( srcs = ["indirect.cc"], hdrs = ["indirect.h"], copts = ["-Iexternal/value_types/"], - defines = ["XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION"], + defines = [], visibility = ["//visibility:public"], deps = ["feature_check"], ) @@ -92,8 +92,9 @@ cc_library( srcs = ["polymorphic.cc"], hdrs = ["polymorphic.h"], copts = ["-Iexternal/value_types/"], - defines = ["XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION"], + defines = [], visibility = ["//visibility:public"], + deps = ["feature_check"], ) cc_test( @@ -117,6 +118,7 @@ cc_library( copts = ["-Iexternal/value_types/"], defines = ["XYZ_POLYMORPHIC_CXX_14"], visibility = ["//visibility:public"], + deps = ["feature_check"], ) cc_test( diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e151aa8..9ea6f117 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,6 @@ target_sources(xyz_value_types xyz_add_library( NAME indirect ALIAS xyz_value_types::indirect - DEFINITIONS XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION ) target_sources(indirect INTERFACE @@ -76,7 +75,6 @@ target_sources(indirect_cxx17 xyz_add_library( NAME polymorphic ALIAS xyz_value_types::polymorphic - DEFINITIONS XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION ) target_sources(polymorphic INTERFACE diff --git a/indirect.h b/indirect.h index 09b5eba2..f491faeb 100644 --- a/indirect.h +++ b/indirect.h @@ -31,6 +31,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace xyz { +#ifndef XYZ_TYPE_IDENTITY_DEFINED +#define XYZ_TYPE_IDENTITY_DEFINED +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +using std::type_identity_t; +#else +template +struct type_identity { + using type = T; +}; +template +using type_identity_t = typename type_identity::type; +#endif // XYZ_HAS_STD_TYPE_IDENTITY +#endif // XYZ_TYPE_IDENTITY_DEFINED + #ifndef XYZ_UNREACHABLE_DEFINED #define XYZ_UNREACHABLE_DEFINED @@ -182,7 +196,7 @@ class indirect { p_ = construct_from(alloc_, ilist, std::forward(us)...); } - constexpr indirect(std::allocator_arg_t, const std::type_identity_t& alloc, + constexpr indirect(std::allocator_arg_t, const xyz::type_identity_t& alloc, const indirect& other) : alloc_(alloc) { static_assert(std::copy_constructible); @@ -195,7 +209,7 @@ class indirect { } constexpr indirect( - std::allocator_arg_t, const std::type_identity_t& alloc, + std::allocator_arg_t, const xyz::type_identity_t& alloc, indirect&& other) noexcept(allocator_traits::is_always_equal::value) : p_(nullptr), alloc_(alloc) { static_assert(std::move_constructible); @@ -465,16 +479,12 @@ concept is_hashable = requires(T t) { std::hash{}(t); }; template indirect(Value) -> indirect; -template , int> = 0> -indirect(std::allocator_arg_t, Alloc, Value) -> indirect< - Value, typename std::allocator_traits::template rebind_alloc>; - -#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION template -indirect(std::allocator_arg_t, std::type_identity_t, - indirect) -> indirect; -#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION +indirect(std::allocator_arg_t, Alloc, Value) -> indirect; + +template +indirect(std::allocator_arg_t, Alloc2, indirect) + -> indirect; } // namespace xyz diff --git a/indirect_cxx14.h b/indirect_cxx14.h index c45aeb7c..8883ab76 100644 --- a/indirect_cxx14.h +++ b/indirect_cxx14.h @@ -36,6 +36,20 @@ namespace xyz { struct in_place_t {}; #endif // XYZ_IN_PLACE_DEFINED +#ifndef XYZ_TYPE_IDENTITY_DEFINED +#define XYZ_TYPE_IDENTITY_DEFINED +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +using std::type_identity_t; +#else +template +struct type_identity { + using type = T; +}; +template +using type_identity_t = typename type_identity::type; +#endif // XYZ_HAS_STD_TYPE_IDENTITY +#endif // XYZ_TYPE_IDENTITY_DEFINED + #ifndef XYZ_UNREACHABLE_DEFINED #define XYZ_UNREACHABLE_DEFINED @@ -575,8 +589,11 @@ template indirect(Value) -> indirect; template -indirect(std::allocator_arg_t, Alloc, Value) -> indirect< - Value, typename std::allocator_traits::template rebind_alloc>; +indirect(std::allocator_arg_t, Alloc, Value) -> indirect; + +template +indirect(std::allocator_arg_t, Alloc2, indirect) + -> indirect; #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION } // namespace xyz diff --git a/indirect_test.cc b/indirect_test.cc index f80b9570..d99b1666 100644 --- a/indirect_test.cc +++ b/indirect_test.cc @@ -133,15 +133,13 @@ TEST(IndirectTest, TemplateArgumentDeductionCopy) { } TEST(IndirectTest, TemplateArgumentDeductionWithAllocator) { - xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); + xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); static_assert( std::is_same_v>); EXPECT_EQ(*i, 42); } -#ifdef XYZ_HAS_STD_TYPE_IDENTITY -#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { xyz::indirect i(std::allocator_arg, xyz::TaggedAllocator(1), 42); xyz::indirect ii(std::allocator_arg, 2, i); @@ -158,8 +156,6 @@ TEST(IndirectTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { EXPECT_EQ(*ii, 42); EXPECT_EQ(ii.get_allocator().tag, 2); } -#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION -#endif // XYZ_HAS_STD_TYPE_IDENTITY #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION template > diff --git a/polymorphic.h b/polymorphic.h index b27a6ca6..99e9d013 100644 --- a/polymorphic.h +++ b/polymorphic.h @@ -33,6 +33,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace xyz { +#ifndef XYZ_TYPE_IDENTITY_DEFINED +#define XYZ_TYPE_IDENTITY_DEFINED +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +using std::type_identity_t; +#else +template +struct type_identity { + using type = T; +}; +template +using type_identity_t = typename type_identity::type; +#endif // XYZ_HAS_STD_TYPE_IDENTITY +#endif // XYZ_TYPE_IDENTITY_DEFINED + #ifndef XYZ_UNREACHABLE_DEFINED #define XYZ_UNREACHABLE_DEFINED @@ -119,12 +133,6 @@ class direct_control_block final : public control_block { template class polymorphic; -template -inline constexpr bool is_polymorphic_v = false; - -template -inline constexpr bool is_polymorphic_v> = true; - template > class polymorphic { using cblock_t = detail::control_block; @@ -251,7 +259,7 @@ class polymorphic { } constexpr polymorphic(std::allocator_arg_t, - const std::type_identity_t& alloc, + const xyz::type_identity_t& alloc, const polymorphic& other) : alloc_(alloc) { if (!other.valueless_after_move()) { @@ -262,7 +270,7 @@ class polymorphic { } constexpr polymorphic( - std::allocator_arg_t, const std::type_identity_t& alloc, + std::allocator_arg_t, const xyz::type_identity_t& alloc, polymorphic&& other) noexcept(allocator_traits::is_always_equal::value) : alloc_(alloc) { if constexpr (allocator_traits::is_always_equal::value) { @@ -414,19 +422,17 @@ class polymorphic { } } }; -#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION + template polymorphic(Value) -> polymorphic; -template , int> = 0> -polymorphic(std::allocator_arg_t, Alloc, Value) -> polymorphic< - Value, typename std::allocator_traits::template rebind_alloc>; - template -polymorphic(std::allocator_arg_t, std::type_identity_t, - polymorphic) -> polymorphic; -#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION +polymorphic(std::allocator_arg_t, Alloc, Value) -> polymorphic; + +template +polymorphic(std::allocator_arg_t, Alloc2, polymorphic) + -> polymorphic; + } // namespace xyz #endif // XYZ_POLYMORPHIC_H_ diff --git a/polymorphic_cxx14.h b/polymorphic_cxx14.h index 5b611b26..d75c07ca 100644 --- a/polymorphic_cxx14.h +++ b/polymorphic_cxx14.h @@ -27,6 +27,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include "feature_check.h" + #ifndef XYZ_POLYMORPHIC_HAS_EXTENDED_CONSTRUCTORS #define XYZ_POLYMORPHIC_HAS_EXTENDED_CONSTRUCTORS 1 #endif // XYZ_POLYMORPHIC_HAS_EXTENDED_CONSTRUCTORS @@ -40,6 +42,22 @@ struct in_place_type_t {}; } // namespace xyz #endif // XYZ_IN_PLACE_TYPE_DEFINED +#ifndef XYZ_TYPE_IDENTITY_DEFINED +#define XYZ_TYPE_IDENTITY_DEFINED +namespace xyz { +#ifdef XYZ_HAS_STD_TYPE_IDENTITY +using std::type_identity_t; +#else +template +struct type_identity { + using type = T; +}; +template +using type_identity_t = typename type_identity::type; +#endif // XYZ_HAS_STD_TYPE_IDENTITY +} // namespace xyz +#endif // XYZ_TYPE_IDENTITY_DEFINED + #ifndef XYZ_UNREACHABLE_DEFINED #define XYZ_UNREACHABLE_DEFINED @@ -319,7 +337,8 @@ class polymorphic : private detail::empty_base_optimization { typename std::remove_reference::type>::type>{}, std::forward(u)) {} - polymorphic(std::allocator_arg_t, const A& alloc, const polymorphic& other) + polymorphic(std::allocator_arg_t, const xyz::type_identity_t& alloc, + const polymorphic& other) : alloc_base(alloc) { if (!other.valueless_after_move()) { cb_ = other.cb_->clone(alloc_base::get()); @@ -335,7 +354,7 @@ class polymorphic : private detail::empty_base_optimization { other) {} polymorphic( - std::allocator_arg_t, const A& alloc, + std::allocator_arg_t, const xyz::type_identity_t& alloc, polymorphic&& other) noexcept(allocator_traits::is_always_equal::value) : alloc_base(alloc) { if (allocator_traits::propagate_on_container_copy_assignment::value) { @@ -476,6 +495,18 @@ class polymorphic : private detail::empty_base_optimization { } }; +#ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION +template +polymorphic(Value) -> polymorphic; + +template +polymorphic(std::allocator_arg_t, Alloc, Value) -> polymorphic; + +template +polymorphic(std::allocator_arg_t, Alloc2, polymorphic) + -> polymorphic; +#endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION + } // namespace xyz #endif // XYZ_POLYMORPHIC_H_ diff --git a/polymorphic_test.cc b/polymorphic_test.cc index e0b8c007..725399d2 100644 --- a/polymorphic_test.cc +++ b/polymorphic_test.cc @@ -846,8 +846,6 @@ TEST(PolymorphicTest, TaggedAllocatorsNotEqualMoveConstructFromValueless) { } #ifdef XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION -#ifdef XYZ_HAS_STD_TYPE_IDENTITY -#ifdef XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION TEST(PolymorphicTest, TemplateArgumentDeduction) { xyz::polymorphic p(Derived(4)); @@ -864,7 +862,7 @@ TEST(PolymorphicTest, TemplateArgumentDeductionCopy) { } TEST(PolymorphicTest, TemplateArgumentDeductionWithAllocator) { - xyz::TaggedAllocator a(1); + xyz::TaggedAllocator a(1); xyz::polymorphic p(std::allocator_arg, a, Derived(4)); EXPECT_EQ(p->value(), 4); @@ -872,7 +870,7 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithAllocator) { } TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { - xyz::TaggedAllocator a(1); + xyz::TaggedAllocator a(1); xyz::polymorphic p(std::allocator_arg, a, Derived(4)); xyz::polymorphic pp(std::allocator_arg, 2, p); @@ -881,7 +879,7 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndCopy) { } TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { - xyz::TaggedAllocator a(1); + xyz::TaggedAllocator a(1); xyz::polymorphic p(std::allocator_arg, a, Derived(4)); xyz::polymorphic pp(std::allocator_arg, 2, std::move(p)); @@ -889,8 +887,6 @@ TEST(PolymorphicTest, TemplateArgumentDeductionWithDeducedAllocatorAndMove) { EXPECT_EQ(pp.get_allocator().tag, 2); } -#endif // XYZ_HAS_EXTENDED_CONSTRUCTOR_TEMPLATE_ARGUMENT_DEDUCTION -#endif // XYZ_HAS_STD_TYPE_IDENTITY #endif // XYZ_HAS_TEMPLATE_ARGUMENT_DEDUCTION } // namespace