It is using members like

_M_dataplus

(underscore + uppercase letter) which are not allowed for user code in general.

So unless the implementation specifically allows it, it is on your own risk.

 

-----Ursprüngliche Nachricht-----
Von: Srik Wanar via Std-Proposals <std-proposals@lists.isocpp.org>
Gesendet: Di 17.06.2025 13:05
Betreff: Re: [std-proposals] I have a span but I need a container
An: std-proposals@lists.isocpp.org;
CC: Srik Wanar <srik_wanar@yeah.net>;

You can Indeed achieve it without ub, with digging deep into the standard library's implementation,

which cannot be avoided as you always need the layout.

 

https://godbolt.org/z/YbsY51hjn

 

 

 

 

 

 

 
 

 


At 2025-06-17 07:01:45, "Frederick Virchanza Gotham via Std-Proposals" <std-proposals@lists.isocpp.org> wrote: >I'm writing a program at the moment using the wxWidgets library for >showing windows on screen. Some of the constant strings in the program >are very long, and they get copied in a few places because some of the >wxWidgets library functions take a "wxString const &" as an argument. >wxString is similar to std::string in that it provides storage for the >string and allocates memory dynamically if necessary, and so all my >constexpr strings gets copied when I create the wxString object. > >For the purposes of this email I'm going to switch over to the C++ >standard library, and so I'll talk about the std::string class. Let's >say there's a function in a 3rd party library as follows: > >    size_t CountWords(string const &s) >    { >        std::size_t count = 1u; >        for ( char const c : s ) >        { >            if ( c == ' ' ) ++count; >        } >        return count; >    } > >Now we could argue that this function should really take a 'char*' or >a 'string_view', but let's assume that we can't change a pre-compiled >proprietary library. It takes a 'string' and we just have to deal with >it. > >Now let's say we have a semi-long constexpr string as follows: > >    constexpr char g_poem[] = >        "Had I the heavens’ embroidered cloths,\n" >        "Enwrought with golden and silver light,\n" >        "The blue and the dim and the dark cloths\n" >        "Of night and light and the half-light,\n" >        "I would spread the cloths under your feet:\n" >        "But I, being poor, have only my dreams;\n" >        "I have spread my dreams under your feet;\n" >        "Tread softly because you tread on my dreams."; > >This string is not nearly as long as some of the strings I have >hardcoded into my current program (e.g. the full hex values of a PDF >file for a C++ proposal paper). But let's say that we really don't >want to copy this string. Some how, some way, though, we need to pass >this as a 'std::string const &' without copying the string. > >So we start out with a structure that can pretend it's an 'std::string': > >    template<typename T> requires std::is_same_v< T, std::remove_cvref_t<T> > >    struct Pretender { >        union { >            alignas(T) char unsigned  m8[sizeof(T)]; >            alignas(T) std::uint16_t m16[sizeof(T) / sizeof(std::uint16_t)]; >            alignas(T) std::uint32_t m32[sizeof(T) / sizeof(std::uint32_t)]; >            alignas(T) std::uint64_t m64[sizeof(T) / sizeof(std::uint64_t)]; >            alignas(T)    void const *mp[sizeof(T) / sizeof(    void*    )]; >        }; > >        Pretender(void) : m8() {}  // start off all bits zero > >        operator T const&(void) const noexcept >        { >            return *static_cast<T const*>(static_cast<void const*>(this)); >        } >    }; > >And from there we can write a function as follows to pretend that a >span is a container: > >    template<typename T> requires std::is_same_v< T, std::remove_cvref_t<T> > >    Pretender<T> Pretend(typename T::value_type const *const p, >std::size_t const len); > >So then in the implementation of this function, we put specialist code >for 'std::string' as follows for libstdc++: > >    template<typename T> requires std::is_same_v< T, std::remove_cvref_t<T> > >    Pretender<T> Pretend(typename T::value_type const *const p, >std::size_t const len) >    { >        Pretender<T> retval; >        if constexpr ( std::is_same_v<T, std::string> ) >        { >            static_assert( sizeof(std::string) == 32u ); >            retval.mp [0] = p; >            retval.m64[1] = len; >            retval.m64[2] = len; >        } >        return retval; >    } > >So now let's try it in a GodBolt to see if it works: > >    https://godbolt.org/z/djWf3q3Gc > >This strategy also works for other contiguous containers. Let's say we >have a 3rd party library with an exported function such as: > >    void Func( std::vector<double> const & ); > >But all we have is a std::span<double>. Well we can pretend that the >span is a vector: > >    https://godbolt.org/z/59WfGz3f4 > >The key here is that the make-believe container must be 'const' -- >meaning that you can't edit its elements, can't resize it, and very >importantly, you can't move from it. > >Is there any possibility we could have something like this in the >Standard? It can be implemented without an ABI break. I can implement >it in a day or two for all the major C++ standard libraries. . . >Dinkumware, Microsoft, libstdc++, libc++. It's not much work. > >In my own program I'll be using this strategy to pretend that a >constexpr char array is a wxString object. > >And for those who want to scream at me to say that my implementations >are undefined behaviour, well try to imagine that I compiled it to >assembler, and then I put inline assembler in a C++ file. No more >undefined behaviour. This can be implemented without an ABI break. >--  >Std-Proposals mailing list >Std-Proposals@lists.isocpp.org >https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals 
-- 
 Std-Proposals mailing list
 Std-Proposals@lists.isocpp.org
 https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals