From d65eafe86aeaff4cde931fb144edcb1c3086720d 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 07:31:15 +0000 Subject: [PATCH] fix(uninitialized): Fix MSVC compilation error with std::map node construction The issue occurs when container_allocator calls ipc::construct() with no arguments. MSVC and GCC have different behaviors regarding std::is_constructible for std::map's internal node type. Solution: - Add explicit overload for zero-argument construct() using value initialization T() - Separate overloads for one or more arguments to avoid SFINAE ambiguity - This ensures MSVC uses direct initialization T() instead of aggregate initialization T{} Fixes compilation error on Visual Studio 2017: error C2512: no appropriate default constructor available note: Invalid aggregate initialization --- 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)...}; } /**