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)...}; } /**