Sayantan Ghosh
Sayantan Ghosh

Reputation: 1056

C++ SSO : How to programatically find if a std::wstring is allocated with Short String Optimization?

How to programatically find if a std::wstring is allocated with Short String Optimization? I was trying to detect such cases and use reserve to move out of the SSO.

The below code prints a small difference in the addresses:

#include <string>
#include <iostream>
int main () 
{
    std::wstring str = L"H";
    std::cout<<&str<<" "<<(void*)str.data()<<"\n";
} 

Output example:

0x7ffc39465220 0x7ffc39465230

enter image description here

Although in windows console app the address comes exactly same:

enter image description here

Upvotes: 3

Views: 524

Answers (2)

Deduplicator
Deduplicator

Reputation: 45684

There are two main ways to go about it:

  1. Just straight-up test it.

    Remember to use std::less to get a full order, and std::addressof to account for overloaded op& in weird classes.

    template <class T>
    constexpr bool uses_sbo(T&& t) noexcept {
        auto less = std::less<const volatile void*>();
        auto p = std::addressof(t);
        return less(t.data(), p + 1) && !less(p, t.data()));
    }
    
  2. Compare the capacity.

    This relies on the implementation being sensible, meaning never allocating dynamically when the current capacity suffices, and not dynamically allocating an initial buffer on principle.

    template <class T>
    constexpr bool is_minimal(T&& t) noexcept {
        return t.capacity() == T().capacity();
    }
    

Both were generalized for all contiguous containers.

Upvotes: 6

Marek R
Marek R

Reputation: 38112

template<typename T>
bool ssoTest1(const std::basic_string<T>& s)
{
    return s.capacity() == std::basic_string<T>{}.capacity();
}

template<typename T>
bool ssoTest2(const std::basic_string<T>& s)
{
    uintptr_t r = s.data() - reinterpret_cast<const T*>(&s);
    return r <= sizeof(s);
}

https://godbolt.org/z/v3b57Y

Upvotes: 1

Related Questions