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>&lt;T&gt;</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

Reply via email to