Backl1ght wrote:

> So, friend functions do not increase the template depth? That seems... weird!

This is not the cause, as for template depth friend functions behave just the 
same as other functions I think. Maybe you are confused by my first comment in 
https://github.com/llvm/llvm-project/issues/98258 , that is incorrect cause I 
made a stupid mistake.

As we are allowed to use generic lambda inside requires-clause, a friend 
function template can reference to a value below the template depth of the 
friend function. 

For example, the `X` has a template depth of 1 while `f3` has a template depth 
of 0.

```cpp
struct S {
  template <typename U>
  friend void f3() requires requires { []<int X>(){ return X; }; } {
    return;
  }
};
```

```plain text
`-FriendDecl 0xd461268 <line:2:3, line:5:3> line:3:15
    `-FunctionTemplateDecl 0xd43f638 parent 0xd3ebd28 <line:2:3, line:5:3> 
line:3:15 friend_undeclared f3
      |-TemplateTypeParmDecl 0xd43ead0 <line:2:13, col:22> col:22 typename 
depth 0 index 0 U
      `-FunctionDecl 0xd43f548 parent 0xd3ebd28 <line:3:3, line:5:3> line:3:15 
friend_undeclared f3 'void ()' implicit-inline
        |-RequiresExpr 0xd43f4b0 <col:29, col:66> 'bool'
        | `-SimpleRequirement 0xd43f480 dependent
        |   `-LambdaExpr 0xd43f458 <col:40, col:63> 'S::(lambda at 
<source>:3:40)'
        |     |-CXXRecordDecl 0xd43ebf0 <col:40> col:40 implicit class 
definition
        |     | |-DefinitionData generic lambda empty standard_layout 
trivially_copyable trivial literal has_constexpr_non_copy_move_ctor 
can_const_default_init
        |     | | |-DefaultConstructor exists trivial constexpr needs_implicit 
defaulted_is_constexpr
        |     | | |-CopyConstructor simple trivial has_const_param 
needs_implicit implicit_has_const_param
        |     | | |-MoveConstructor exists simple trivial needs_implicit
        |     | | |-CopyAssignment simple trivial has_const_param 
needs_implicit implicit_has_const_param
        |     | | |-MoveAssignment exists simple trivial needs_implicit
        |     | | `-Destructor simple irrelevant trivial constexpr 
needs_implicit
        |     | |-FunctionTemplateDecl 0xd43eea8 <<invalid sloc>, col:63> 
col:40 operator()
        |     | | |-NonTypeTemplateParmDecl 0xd43ee30 <col:43, col:47> col:47 
referenced 'int' depth 1 index 0 X
        |     | | `-CXXMethodDecl 0xd43ed58 <col:50, col:63> col:40 constexpr 
operator() 'auto () const' inline
        |     | |   `-CompoundStmt 0xd43f0d8 <col:51, col:63>
        |     | |     `-ReturnStmt 0xd43f0c8 <col:53, col:60>
        |     | |       `-DeclRefExpr 0xd43f0a8 <col:60> 'int' 
NonTypeTemplateParm 0xd43ee30 'X' 'int'
        |     | |-FunctionTemplateDecl 0xd43f2d0 <<invalid sloc>, col:63> 
col:40 implicit operator auto (*)()
        |     | | |-NonTypeTemplateParmDecl 0xd43ee30 <col:43, col:47> col:47 
referenced 'int' depth 1 index 0 X
        |     | | `-CXXConversionDecl 0xd43f218 <col:40, col:63> col:40 
implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
        |     | `-FunctionTemplateDecl 0xd43f3e8 <<invalid sloc>, col:63> 
col:40 implicit __invoke
        |     |   |-NonTypeTemplateParmDecl 0xd43ee30 <col:43, col:47> col:47 
referenced 'int' depth 1 index 0 X
        |     |   `-CXXMethodDecl 0xd43f338 <col:40, col:63> col:40 implicit 
__invoke 'auto ()' static inline
        |     `-CompoundStmt 0xd43f0d8 <col:51, col:63>
        |       `-ReturnStmt 0xd43f0c8 <col:53, col:60>
        |         `-DeclRefExpr 0xd43f0a8 <col:60> 'int' NonTypeTemplateParm 
0xd43ee30 'X' 'int'
        `-CompoundStmt 0xd461380 <col:68, line:5:3>
          `-ReturnStmt 0xd461370 <line:4:5>
```

https://godbolt.org/z/6TxrGdM35

We can make this example more complicated, like place a generic lambda inside a 
generic lambda.
https://godbolt.org/z/E6G5qv7v1

https://github.com/llvm/llvm-project/pull/99813
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to