Reputation: 1056
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
Although in windows console app the address comes exactly same:
Upvotes: 3
Views: 524
Reputation: 45684
There are two main ways to go about it:
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()));
}
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
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);
}
Upvotes: 1