10

The main purpose of this question is to draw community's attention to libstdc++ ranges not working with clang: https://bugs.llvm.org/show_bug.cgi?id=46746

Avi Kivity suggested this is a gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97120

But then he also suggested this is a clang bug: https://bugs.llvm.org/show_bug.cgi?id=47509

Rafael Ávila de Espíndola boiled down the problem to the following code, which compiles with gcc, but not with clang:

template <typename _Tp>
concept __member_begin = requires(_Tp __t) {
    {__t.begin()};
};
template <typename _Tp>
concept nothing = requires(_Tp __t) {
    {42};
};
template <typename _Tp>
requires __member_begin<_Tp> void __ranges_begin() {}
template <typename _Derived>
struct view_interface {
    void foo() requires __member_begin<_Derived> {}
    void bar() requires nothing<decltype(__ranges_begin<_Derived>())> {}
};
struct drop_view : public view_interface<drop_view> {};

clang complains (https://godbolt.org/z/4c45oKMKK):

<source>:14:42: error: no matching function for call to '__ranges_begin'
    void bar() requires nothing<decltype(__ranges_begin<_Derived>())> {}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~

So the question is, who is right? Should this code compile or not?

And the more interesting question: can we please have working ranges with clang?

cigien
  • 57,834
  • 11
  • 73
  • 112
Mikhail
  • 20,685
  • 7
  • 70
  • 146
  • 1
    Asking "who is right?" requires referring to the standard, making this a language-lawyer question. Only having 5 tags means I had to pick other tags to remove, and the compiler tags seemed to be the best choice. Feel free to edit the tags if you want, but [c++] and [language-lawyer] should be in there. – cigien Jun 24 '21 at 15:38
  • Generally speaking, I am not sure if SO Question is the best way to "draw community's attention to libstdc++ ranges not working with clang". – SergeyA Jun 24 '21 at 15:40
  • 2
    @SergeyA: There's a surprisingly high number of people on SO who are deeply familiar with the C++ standard, including quite a few of its authors. – MSalters Jun 24 '21 at 15:49
  • @MSalters I am not surprised by it, I am well aware of this fact. However, I am not sure that those people actively monitor question queue. I would believe, there are dedicated groups where such a message will be more visible. – SergeyA Jun 24 '21 at 15:52
  • I would hope that SFINAE would not apply to requires clauses. It isn't needed (everything you can do with SFINAE you can do without in a requires clause), and it is conceptually complex. Also, "have a member" requires shouldn't hard error just because someone called it, that makes auditing of requires clauses a pain. So I hope clang is right. – Yakk - Adam Nevraumont Jun 24 '21 at 19:30

2 Answers2

7

[temp.inst]/17:

The type-constraints and requires-clause of a template specialization or member function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in [temp.constr.decl] and [temp.constr.atomic] when determining whether the constraints are satisfied or as specified in [temp.constr.decl] when comparing declarations.

Clang bug.

T.C.
  • 133,968
  • 17
  • 288
  • 421
4

Following the link from T.C.'s answer I found a related example in the standard, that clang refuses to compile. This is a clear indication of a bug in clang.

[temp.constr.decl]/4:

template <class T> concept C = true;
template <class T> struct A {
  template <class U> U f(U) requires C<typename T::type>;   // #1
  template <class U> U f(U) requires C<T>;                  // #2
};

template <> template <class U>
U A<int>::f(U u) requires C<int> { return u; }              // OK, specializes #2

clang output:

<source>:3:49: error: type 'int' cannot be used prior to '::' because it has no members
  template <class U> U f(U) requires C<typename T::type>;   // #1
                                                ^

I created a dedicated bug for this: https://bugs.llvm.org/show_bug.cgi?id=50864

Mikhail
  • 20,685
  • 7
  • 70
  • 146