<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/57132>57132</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            std::basic_string rejects fancy pointers
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          philnik777
      </td>
    </tr>
</table>

<pre>
    Here is a reproducer: [(Godbolt)](https://godbolt.org/z/sTe1jd6Kd)
```c++
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <cstddef>
#include <string>

template <class T>
class alignas(std::max(alignof(T), alignof(std::ptrdiff_t))) OffsetPtr {
  std::ptrdiff_t offset;

public:
  OffsetPtr() = default;

  OffsetPtr(const OffsetPtr& other) : offset(other.operator->() - reinterpret_cast<T*>(this)) {}

  OffsetPtr& operator=(const OffsetPtr& other) {
    T* ptr = other.operator->();
    offset = ptr - reinterpret_cast<T*>(this);
  }

  explicit OffsetPtr(T* ptr) : offset(ptr - reinterpret_cast<T*>(this)) {}
  T* operator->() const { return reinterpret_cast<T*>(const_cast<OffsetPtr*>(this)) + offset; }
  T& operator[](size_t i) { return operator->()[i]; }

  static OffsetPtr pointer_to(T& e) { return OffsetPtr(&e); }
};

template <class T>
class OffsetPtrAllocator {
public:
  using value_type = T;
  using pointer    = OffsetPtr<T>;

  pointer allocate(size_t n) { return pointer(std::allocator<T>{}.allocate(n)); }

  void deallocate(pointer ptr, size_t n) { std::allocator<T>{}.deallocate(ptr.operator->(), n); }
};

int main() {
  using string = std::basic_string<char, std::char_traits<char>, OffsetPtrAllocator<char>>;
  string str1  = "long long string so no SSO";
  string str2;
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9Vttu4zYQ_Rr5hbChiy05D3rwJdkNNu0GiNH2zaBEyuYuLQoklSb79R2SoiUrzqYFijXoizgzZ85cOGYhyGv-mUqKmEIYSdpIQdqSyiBZoWCxDuLlJ0EKwXUQ3wSLLTwftW4UiIP4DtbBSWdCHuDpB7zVjkbfSPqFGItwG4SrIA3dKoN4bZbbtfZBsnVr-r-8znAd-tDT4Dd6xFIjUSF9pOjh4Y_f0KMU32gJUW5QWxMqrWTV4NIosJLWiqLneBaiv5k-OpPbl5I2molazS6wnyhFl0ni_PnUZejhfnP7-9PtTL9oVAmJeIfNang6YQM3Qnvc_jXtGEzvCa01q5irj6M3Naz-vN99tqym1LN6L_ZfkvHOX8LqkreEoiDZlEoTQqsgub0mVVqy-tAL7aemp4Zj7cw5VgrtzhruGXN2qLGCtgR0k-9kdcIv8GgFooJfO9OHUNZ-56zaaElYVe1tc9uFvlaVovpRSxRkXaMi9NYAesfoBcl6yLdpC6inUe0Mz2jg1aBDmhDkALd8bHqpW0JT6eFOigQ0pHQYK-89XtrdmWioxFrIqcmO8zSFs8xqTWUjqd6XWIHDDaRi5VT0kakuYhNntn2XC3ju0G2Nf06tTxlCxhlqTCIh6Pd4nrNgLFxUVt_Y_csQeoQ3YdCXBurBLuguPa83ufwPPkdp64K9UgaXLdAFXN3K-ufwVttvDzhf8R6v-xZEl0QGFYMBbme2Yj8oNC3riHsyV-qxWDNjMgTtTwGMp3JwQhphY9lr4dKaIjpycNn_KXX1GkBn29E5-PjInzFXnIvS0O_77s0BbBVMFfSMeQvxvzbUNtdu0DNOoYvENKFR6Gmb6oD78Vn1-thRoH2K61EGOs3h1MGet0e3nTQbYNXdPLpWhWfBCMyQgbYnY3t6g8ZEPvJ7iaWvnlKArT-uHdBAJ8xqP-yyUZbdjLcZPpMqsGLl3k__TXnELggvNxt7LTHTyosNq82VNhjIByVD3i18Ra68QRxzATv2w0sFqgV6evoKwqu2_W6fAX-vmdA8StMwWS4W82RC8oTcJDd4opnmNL8aKrSHuW4oVOG6fPVdoiat5PnoggX3jbaYleLUXSS6r2njbyx3TKmWwmS4W2RREk-OeTGv5jSrykVBM7JIb5ZRWWXJMswKkoRGheOCcpXbC17MWeEvZhD7YjtheRzGcbiMkiiM4hjuF0lcpMsEE0LmMYmqYB5SKDSf-YvNROaWU9EeFAg5U1r1Qji18NdLae7m0QS3-ihk3hwZr9n3LMsmNoLc0v8HlawLdQ">