From 0c78623bccc68fc08a4b9e5ba9255801a2fe0604 Mon Sep 17 00:00:00 2001 From: Duncan Horn Date: Mon, 14 Jul 2025 14:14:22 -0700 Subject: [PATCH 1/2] Fix the issue --- include/wil/win32_helpers.h | 37 ++++++++++++++++++++++++++++++------- tests/wiTest.cpp | 5 +++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/wil/win32_helpers.h b/include/wil/win32_helpers.h index d87a4f3de..44fd625d1 100644 --- a/include/wil/win32_helpers.h +++ b/include/wil/win32_helpers.h @@ -959,17 +959,40 @@ bool init_once(_Inout_ INIT_ONCE& initOnce, T func) /// @cond namespace details { + // NOTE: We can't have a 'using std::begin' at class scope, hence the workaround for handling both 'begin' with ADL + // and 'std::begin' separately. We want to handle both because there's no guarantee the type has a 'begin' method template + struct deduce_char_type_from_string_range_traits + { + template + static std::true_type deduce_has_adl_begin(U&& range, std::void_t*); + template + static std::false_type deduce_has_adl_begin(U&&, ...); + + template + static std::true_type deduce_has_std_begin(U&& range, std::void_t*); + template + static std::false_type deduce_has_std_begin(U&&, ...); + + static constexpr bool has_adl_begin = decltype(deduce_has_adl_begin(std::declval(), nullptr))::value; + static constexpr bool has_std_begin = decltype(deduce_has_std_begin(std::declval(), nullptr))::value; + }; + + template ::has_adl_begin, bool hasStdBegin = deduce_char_type_from_string_range_traits::has_std_begin> struct deduce_char_type_from_string_range { - template - static auto deduce(T& range) - { - using std::begin; - return (*begin(range))[0]; - } + }; - using type = decltype(deduce(wistd::declval())); + template + struct deduce_char_type_from_string_range + { + using type = std::decay_t()))[0])>; + }; + + template + struct deduce_char_type_from_string_range + { + using type = std::decay_t()))[0])>; }; template diff --git a/tests/wiTest.cpp b/tests/wiTest.cpp index 508efe2a6..d2763fbaf 100644 --- a/tests/wiTest.cpp +++ b/tests/wiTest.cpp @@ -4220,6 +4220,11 @@ TEST_CASE("WindowsInternalTests::ArgvToCommandLine", "[win32_helpers]") {L"test", L"This\u00A0string\u180Ehas\u2000no\u2001space\u2002characters\u2003even\u2004though\u2005it\u2006contains\u2007characters\u2008that\u2009look\u200Athe\u200Bsame\u200Cor\u200Dare\u202Fsometimes\u205Ftreated\u2060the\u2800same\u3000as\u3164whitespace"}, L"test This\u00A0string\u180Ehas\u2000no\u2001space\u2002characters\u2003even\u2004though\u2005it\u2006contains\u2007characters\u2008that\u2009look\u200Athe\u200Bsame\u200Cor\u200Dare\u202Fsometimes\u205Ftreated\u2060the\u2800same\u3000as\u3164whitespace", L"\"test\" \"This\u00A0string\u180Ehas\u2000no\u2001space\u2002characters\u2003even\u2004though\u2005it\u2006contains\u2007characters\u2008that\u2009look\u200Athe\u200Bsame\u200Cor\u200Dare\u202Fsometimes\u205Ftreated\u2060the\u2800same\u3000as\u3164whitespace\""); + + // Finally, ensure that we can call the argc+argv version using the default flags + const char* const argvArray[] = { "test.exe", "foo", "bar" }; // Simple... this is just to verify we can call it + auto cmdLine = wil::ArgvToCommandLine(3, argvArray); + REQUIRE(cmdLine == "test.exe foo bar"); } #endif From 6b7883a5d0810d087d491dc875f65e0871b26718 Mon Sep 17 00:00:00 2001 From: Duncan Horn Date: Mon, 14 Jul 2025 14:14:58 -0700 Subject: [PATCH 2/2] 4mat --- tests/wiTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wiTest.cpp b/tests/wiTest.cpp index d2763fbaf..931610a8f 100644 --- a/tests/wiTest.cpp +++ b/tests/wiTest.cpp @@ -4222,7 +4222,7 @@ TEST_CASE("WindowsInternalTests::ArgvToCommandLine", "[win32_helpers]") L"\"test\" \"This\u00A0string\u180Ehas\u2000no\u2001space\u2002characters\u2003even\u2004though\u2005it\u2006contains\u2007characters\u2008that\u2009look\u200Athe\u200Bsame\u200Cor\u200Dare\u202Fsometimes\u205Ftreated\u2060the\u2800same\u3000as\u3164whitespace\""); // Finally, ensure that we can call the argc+argv version using the default flags - const char* const argvArray[] = { "test.exe", "foo", "bar" }; // Simple... this is just to verify we can call it + const char* const argvArray[] = {"test.exe", "foo", "bar"}; // Simple... this is just to verify we can call it auto cmdLine = wil::ArgvToCommandLine(3, argvArray); REQUIRE(cmdLine == "test.exe foo bar"); }