Add a guid constructor overload taking Data4 by reference to array - #1622
Add a guid constructor overload taking Data4 by reference to array#1622Daniel Jump (DanielJump) wants to merge 1 commit into
Conversation
|
Does the following code not work? It can avoid source-breaking. #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable: 5246)
constexpr guid(std::uint32_t const Data1, std::uint16_t const Data2, std::uint16_t const Data3, std::uint8_t const (&Data4)[8]) noexcept :
Data1(Data1),
Data2(Data2),
Data3(Data3),
Data4{ Data4[0], Data4[1], Data4[2], Data4[3], Data4[4], Data4[5], Data4[6], Data4[7] }
{
}
#pragma warning(pop)
#endif |
27d21f0 to
1275443
Compare
The guid constructor takes Data4 as std::array<std::uint8_t, 8> const&. Because std::array wraps a C array, a braced call site elides the inner braces and MSVC reports C5246, "the initialization of a subobject should be wrapped in braces", at every such call site - including the guid literals C++/WinRT generates for each namespace header. Suppressing the warning around the constructor does not work, because the diagnostic is attributed to the caller rather than to the constructor. Add an overload taking std::uint8_t const (&)[8] rather than replacing the existing parameter. A braced initializer then binds to the C array directly, with no intervening subobject and no warning, while callers passing a std::array continue to compile unchanged. Measured on a /Wall build of a translation unit exercising collections, coroutines, delegates, implements, factories and classic COM: C5246 falls from 114 to 20, with no other diagnostic changes.
1275443 to
94787ce
Compare
|
Thanks for looking. I tried exactly that, and the suppression turns out not to take effect: C5246 is attributed to the call site rather than to the constructor, so a Reduced repro, MSVC x64, struct G {
std::uint32_t D1; std::uint16_t D2; std::uint16_t D3; std::uint8_t D4[8];
G() = default;
constexpr G(std::uint32_t d1, std::uint16_t d2, std::uint16_t d3, std::array<std::uint8_t,8> const& d4) noexcept
: D1(d1), D2(d2), D3(d3), D4{d4[0],d4[1],d4[2],d4[3],d4[4],d4[5],d4[6],d4[7]} {}
};
constexpr G g1{ 1,2,3, {1,2,3,4,5,6,7,8} }; // <-- warning lands here
To suppress it we would have to do so at every call site, which means all of the generated namespace headers plus any You are right about the source break, though, and thanks for catching it - replacing the parameter does break callers that pass a So I have pushed a different fix: add the I checked for ambiguity across every call shape I could think of, on both MSVC and clang-cl - braced-init-list, Net effect on a |
The
guidconstructor takesData4asstd::array<std::uint8_t, 8> const&. Becausestd::arraywraps a C array, a braced call site elides the inner braces, and MSVC reports C5246 (the initialization of a subobject should be wrapped in braces) at each such call site - including theguidliterals C++/WinRT generates for every namespace header.Change
Add an overload taking
std::uint8_t const (&)[8]alongside the existingstd::arrayone, rather than replacing it. A braced initializer binds to the C array directly, so there is no intervening subobject and no warning, and callers that pass astd::arraykeep compiling unchanged.Why not suppress it at the constructor
The diagnostic is attributed to the caller, not to the constructor definition, so a
push/disable/poparound the constructor has no effect:std::arrayparameter, braced call sitewarning(push/disable: 5246/pop)around the constructor{{...}}std::uint8_t const (&)[8]parameterSuppressing would therefore have to happen at every call site, which includes all of the generated namespace headers and any
guida consumer writes.Why an overload rather than changing the parameter
Replacing the parameter is source-breaking for callers passing a
std::arraylvalue:Adding the overload avoids that. I checked that it does not introduce ambiguity, on MSVC and clang-cl, for braced-init-lists,
constand non-conststd::arraylvalues,std::arraytemporaries, and C array lvalues - all five compile clean with no C5246 and no-Wmissing-braces.Validation
/Wall, MSVC x64,/std:c++20 /permissive-, on a translation unit exercising collections, coroutines, delegates,implements, factories and classic COM: