Issue |
132577
|
Summary |
[libc++] `view_interface` is not `view`
|
Labels |
libc++
|
Assignees |
|
Reporter |
SainoNamkho
|
https://eel.is/c++draft/range.view#6 says
> For a type `T`, <code><em>is-derived-from-view-interface</em><T></code> is `true` if and only if `T` has exactly one public base class `view_interface<U>` for some type `U` and `T` has no base classes of type `view_interface<V>` for any other type `V`.
Is `view_interface<U>` a base of itself? The answer is no. The standard explicit points it out when reflexivity is additionally accepted.
> https://eel.is/c++draft/concept.derived#note-1
> `derived_from<Derived, Base>` is satisfied if and only if `Derived` is publicly and unambiguously derived from `Base`, **or `Derived` and `Base` are the same class type ignoring cv-qualifiers**.
> https://eel.is/c++draft/type.traits#meta.rel
> `Base` is a base class of `Derived` without regard to cv-qualifiers **or `Base` and `Derived` are not unions and name the same class type without regard to cv-qualifiers**
libc++ and MS STL do not exclude `view_interface` from `enable_view`, libstdc++ does not exclude references ([Godbolt link](https://godbolt.org/z/YeM56ePfj)).
```c++
#include <ranges>
using namespace std::ranges;
struct Incomplete;
struct X : view_interface<X> {};
struct Y : view_interface<Incomplete> {};
struct Z : view_interface<X> {};
static_assert(enable_view<X>);
static_assert(enable_view<Y> && enable_view<Z>); // conforming, should reject, maybe a CWG issue is needed
#if defined(_LIBCPP_VERSION) || defined(_MSVC_STL_UPDATE)
static_assert(!enable_view<X&>); // correct
static_assert(enable_view<view_interface<X>>); // wrong
static_assert(enable_view<view_interface<Incomplete>>); // wrong
static_assert(enable_view<view_interface<Y>>); // wrong
#else // libstdc++
static_assert(enable_view<X&>); // wrong
static_assert(!enable_view<view_interface<X>>); // correct
static_assert(!enable_view<view_interface<Incomplete>>); // correct
static_assert(!enable_view<view_interface<Y>>); // correct
#endif
```
Current implemetaion:
https://github.com/llvm/llvm-project/blob/616737c386776b0cfbda888a4d52e6036ccf1af8/libcxx/include/__ranges/enable_view.h#L36-L43
I think the `is_convertible_v<_Op*, view_interface<_Yp>*>` check is unnecessary, as it will have failed in template argument deduction ambiguity when there're multiple such bases.
Maybe this?
```c++
namespace fix {
namespace impl {
template<class T>
view_interface<T> is_derived_from_view_interface_helper(const view_interface<T>*);
}
template<class T>
constexpr bool enable_view = std::derived_from<T, view_base> || requires(T* p) {
requires !std::same_as<decltype(impl::is_derived_from_view_interface_helper(p)), T>;
};
static_assert(enable_view<view_base>);
static_assert(enable_view<X>);
static_assert(enable_view<Y> && enable_view<Z>);
static_assert(!enable_view<X&>);
static_assert(!enable_view<view_interface<X>>);
static_assert(!enable_view<view_interface<Incomplete>>);
static_assert(!enable_view<view_interface<Y>>);
}
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs