From 3d0d65ead28685c2ab60718bb24b72f11a1dedef Mon Sep 17 00:00:00 2001 From: Marco Barbone Date: Tue, 10 Nov 2026 13:14:00 -0500 Subject: [PATCH] Fix spurious double-register instantiation in emulated batch_bool value ctors The unconstrained kernel::set dispatch in emulated batch_bool value ctors instantiated an unrelated batch> register. Emulated array registers are now filled directly (is_emulated_arch), so no foreign register type is instantiated. Assisted-by: Qwen3.8-27B-FP8 --- include/xsimd/arch/xsimd_emulated.hpp | 3 ++- include/xsimd/types/xsimd_batch.hpp | 5 +++-- test/test_batch_bool.cpp | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/xsimd/arch/xsimd_emulated.hpp b/include/xsimd/arch/xsimd_emulated.hpp index e2cd04c91..2eb29c425 100644 --- a/include/xsimd/arch/xsimd_emulated.hpp +++ b/include/xsimd/arch/xsimd_emulated.hpp @@ -697,7 +697,8 @@ namespace xsimd return { typename batch>::register_type { static_cast(values)... } }; } - template + // no A parameter: callers pass no explicit template argument, so deduction stays constrained + template XSIMD_INLINE batch_bool> set(batch_bool> const&, requires_arch>, Values... values) noexcept { static_assert(sizeof...(Values) == batch>::size, "consistent init"); diff --git a/include/xsimd/types/xsimd_batch.hpp b/include/xsimd/types/xsimd_batch.hpp index 448928f02..7de029d71 100644 --- a/include/xsimd/types/xsimd_batch.hpp +++ b/include/xsimd/types/xsimd_batch.hpp @@ -1215,7 +1215,7 @@ namespace xsimd template template XSIMD_INLINE batch_bool::batch_bool(bool val0, bool val1, Ts... vals) noexcept - : batch_bool(kernel::set(batch_bool {}, A {}, val0, val1, static_cast(vals)...)) + : batch_bool(make_register(std::index_sequence<> {}, val0, val1, static_cast(vals)...)) { static_assert(sizeof...(Ts) + 2 == size, "The constructor requires as many arguments as batch elements."); } @@ -1387,7 +1387,8 @@ namespace xsimd template XSIMD_INLINE auto batch_bool::make_register(std::index_sequence<>, V... v) noexcept -> register_type { - return kernel::set(batch_bool(), A {}, v...).data; + // no explicit template argument here: kernel::set would instantiate unrelated register types + return kernel::set(batch_bool(), A {}, v...).data; } /******************************* diff --git a/test/test_batch_bool.cpp b/test/test_batch_bool.cpp index 8f7b941fe..48e8d79d2 100644 --- a/test/test_batch_bool.cpp +++ b/test/test_batch_bool.cpp @@ -1002,4 +1002,20 @@ TEST_CASE_TEMPLATE("batch_bool mask hygiene", B, BATCH_TYPES) } } +#if XSIMD_WITH_EMULATED +TEST_CASE("emulated batch_bool construction") +{ + using M = xsimd::batch_bool>; + + M const all_true(true); + CHECK(all_true.get(0)); + CHECK(all_true.get(M::size - 1)); + + M const lanes(true, false, true); + CHECK(lanes.get(0)); + CHECK_FALSE(lanes.get(1)); + CHECK(lanes.get(2)); +} +#endif + #endif