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