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

    <tr>
        <th>Summary</th>
        <td>
            [libc++] Moving public API names out of the dylib without breaking ABI
        </td>
    </tr>

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

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

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

<pre>
    This is a meta issue discussing how we can move API names "out" of the dylib without breaking ABI. This comes up in the context of various proposals like making exception types `constexpr`-friendly and additional containers too (which may not be a problem for libc++, but for other implementations). Since we implement many of these inside the dylib, we currently can't implement them as constexpr-friendly.

Potential solution:
1. Add way to say where the vtable lives without a key function (e.g. proposal `Foo::virtual`). This may be necessary because we need to move some functions to the dylib that are currently key functions. If `gnu_inline` works as we want it to for key functions, this step may not be required.
2. Implement the public name in the header, but mark it as `gnu_inline`. Provide a definition in the header, which is constexpr friendly.
3. Retain an implementation for that public name inside the dylib for backwards compat purposes and for QOI matters (avoid instantiating the code everywhere since we have a copy in the dylib).

An example based on `string operator+`:

```c++
// Inside the headers:
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>
operator+(const _CharT* __x, const basic_string<_CharT, _Traits, _Allocator>& __y); // implemented below in header, as normal

template <>
_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_GNU_INLINE _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> // do we need inline keyword too?
operator+<char, char_traits<char>, allocator<char> >(char const*, string const&) {
  // implementation
}

// Inside the dylib:
template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); // instantiate the definition
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vl2P4joS_TXmpTRRcJoADzzQNOwizXSzPb1Sv0WVpCDeduys7UDz76_sBEgPI11d6V4pSpSK6-OcOuUYrRUHRbRgk0c2eRph6yptFrIUWika5bo8L94qYUFYQKjJIQhrW4JS2KK1VqgDVPoEJ4ICFdT6SLDcbUFhTRYY57p1jHPQe3AVQXmWIoeTcJVuHeSG8MNHWD5uIwhpCu392gaECg6FVo4-nfc_ohG6tdAY3WiL0oIUHwR1F4I-C2qc0ArcufGp07jQyjr6bAxL4297I0iV8gyoSsCyFH4typAAhSJjwWkNjM9OlSgqqPEMSjvICdCnzCXVsNcGpMgLxh_DtYK8dcGqXUUGRN1Iqkk59NEt4_MIfgpVkOfn-hFqVOeeEUsglBUl3ejxYT2drTGknDx7YhmfukEAV1EN6NnqEV7hRSx-YvGyu--0I-UESrBatr4klvSfxhEsyxJOeAanweIZThWZroqjw1wSSHEke-0VwgedYd-qIpDM-IyiQ3Rthud7o7WPnyyPwrgWJUvjwEBorOczJ1BUkLVo_EuBrQ3MKKLSlxHUY3VN1zy-KQPhuAodoBmSM6zKRrDd-0oOqs2EkkIRS2M4afNhPV0nghMqB8L5sL5tX7w98c7Xah01QwEY-n8rDJU9uTyC7bAV0LS5FEXQ_EW3FWFJ5qKQGs2Hz4r2rroIdkYfvQAQStoLFYR5H6ZTpRj0HH7peRLBK3ktA6pflBiwBvK-lvpVeGFVjsXHCU0ZRrEJHqbRlmwYHL_iPy9bqNE5PzKMz_CoReljOfRac34Yu8ktCehI5twpy17moMKjB1vo5nyB2et-_kW9SwX0iR4H5GipBC-7NLbO-BS6IYNOGz-HaXzVdX9P4-66TGpn5RvGN7C9we7otVdvR3Uj0RGwZFVItBayVYXmzTegf38zKJwdGJZS6iJUkqy7KNn37eNqt8v-vX1aZ5vXlx_Z8nELF-vq5fnn2_p995r93D6v1tnq_Z3HHqEosg4bS1a3tIOEv0k1ZIHPgjSuJS8hyz5DocH81zPwFLLszPicJY_Qk3fVFZWQk9Qn38KbStGC0qZGOezGkNU7ktbvu5fXt_XTPVH_ev5vtn3-vn1e_93cXcCU-rr7dPPo94OTNn4z0izZ3HOcrIoKA1L_zFwXv7d6ylaAt0QXM4RPM__WNYPxpV_aS7k3pYzPgU17scId42GSe16nT1_kfifsbqDuZP2b2fmnEQ21c90j-iKv290vUzsqF0k5T-Y4osV4ymeT6Swez0fVIuVzPpk-5EVSzmcp4TQuOKXz_bygfPIwSUZiwWP-MI7H8ThNkmQeFQ95vh_PJrN4WpRzPmMPMdUoZCTlsY60OYzCcWYxHo9n6WwkMSdpw2GI8-GfnvvDkVl4r295e7DsIZbCOnuL44ST4Rg1cJs8wQ999Iz0--7taOT_qX96KBq1Ri4q55qwRQUWD8JVbR4VumZ845P3j2-N0f-jwjG-CYgs45se1HHB_wgAAP__Z4BC0A">