[libcxx-commits] [PATCH] D62259: shared_ptr changes from library fundamentals (P0414R2)
Arthur O'Dwyer via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 3 12:55:39 PDT 2021
Quuxplusone added inline comments.
================
Comment at: libcxx/include/memory:3912-3913
+ {
+ static_assert(!_VSTD::is_array<_Tp>::value,
+ "std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
+ return __ptr_;
----------------
@cedral wrote:
> using static_assert breaks the ability to include <memory> in a precompiled header and then explicitly define a shared pointer type for export. You should have used enable_if on the return type instead. [...] test.cpp will fail to compile because it attempts to instantiate the [] lookup operator for export. I don't think this is a bug. It needs to do this because it doesn't know which member functions will be called when the exported type is used by clients of the library.
On the one hand, I confirm your understanding of how `template class std::shared_ptr<int[]>` is treated by the compiler. https://godbolt.org/z/7bbasY83G
On the other hand, I cannot reproduce your issue with libc++ itself; the reason is that `_LIBCPP_INLINE_VISIBILITY` expands to a series of attributes including `__attribute__((__exclude_from_explicit_instantiation__))`. If you're seeing the problem only with PCHes, I wonder if there's a bad interaction between PCHes and that attribute.
Alternatively, are you using GCC (or anything else non-Clang)? It seems like GCC doesn't support that attribute, so I think on GCC you're just out of luck by design.
On the third hand, the language-lawyer answer is that your whole program is "ill-formed, no diagnostic required," and so libc++ isn't required to make it work anyway. Users aren't allowed to explicitly instantiate library types like that. One reason is that you don't know the name of the type — is it really `class std::shared_ptr`, or is it `struct std::shared_ptr`, or is `shared_ptr` just an alias for `__shared_ptr`, etc. etc. The more important reason is exactly what you already found out: When you explicitly instantiate a class template, you get //all// its members, including the private ones that you couldn't otherwise mess with, and which might well not be instantiable for your particular type. Example: https://godbolt.org/z/3hb7Wb3Te
Here's a real-world example from libstdc++: `template class std::atomic<void*>;` is a hard error. https://godbolt.org/z/eTq9TWqnK
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62259/new/
https://reviews.llvm.org/D62259
More information about the libcxx-commits
mailing list