From 5d56ef759f0e3b28c27972b8f361aa36e422479b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Mon, 1 Dec 2025 09:58:53 +0000 Subject: [PATCH] refactor(uninitialized): Improve construct() overload resolution IMPROVEMENTS: 1. Add explicit zero-argument overload to avoid SFINAE ambiguity 2. Require at least one argument (A1) for parameterized overloads 3. Better separation between direct initialization and aggregate initialization BENEFITS: - Clearer intent: zero-argument construction is explicitly handled - Avoids potential SFINAE ambiguity when empty parameter pack is used - More maintainable: easier to understand which overload is selected - Consistent with modern C++ best practices for variadic templates TECHNICAL DETAILS: - Zero-arg overload: Always uses T() for value initialization - One-or-more-arg overload: Uses SFINAE to choose between: * T(args...) for types with matching constructor * T{args...} for aggregate types or types with initializer_list ctor This is a code quality improvement and does not fix any compilation issues, but provides better template overload resolution. --- include/libipc/imp/uninitialized.h | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/include/libipc/imp/uninitialized.h b/include/libipc/imp/uninitialized.h index 01b69c8..dd7b109 100644 --- a/include/libipc/imp/uninitialized.h +++ b/include/libipc/imp/uninitialized.h @@ -21,20 +21,32 @@ namespace ipc { * \see https://en.cppreference.com/w/cpp/memory/construct_at */ -template -auto construct(void *p, A &&...args) - -> std::enable_if_t<::std::is_constructible::value, T *> { +// Overload for zero arguments - use value initialization +template +T* construct(void *p) { #if defined(LIBIPC_CPP_20) - return std::construct_at(static_cast(p), std::forward(args)...); + return std::construct_at(static_cast(p)); #else - return ::new (p) T(std::forward(args)...); + return ::new (p) T(); #endif } -template -auto construct(void *p, A &&...args) - -> std::enable_if_t::value, T *> { - return ::new (p) T{std::forward(args)...}; +// Overload for one or more arguments - prefer direct initialization +template +auto construct(void *p, A1 &&arg1, A &&...args) + -> std::enable_if_t<::std::is_constructible::value, T *> { +#if defined(LIBIPC_CPP_20) + return std::construct_at(static_cast(p), std::forward(arg1), std::forward(args)...); +#else + return ::new (p) T(std::forward(arg1), std::forward(args)...); +#endif +} + +// Overload for non-constructible types - use aggregate initialization +template +auto construct(void *p, A1 &&arg1, A &&...args) + -> std::enable_if_t::value, T *> { + return ::new (p) T{std::forward(arg1), std::forward(args)...}; } /**