c++language-lawyerc++20c++-conceptsrequires-clause

Out-of-class definition with requires clause is rejected by clang but works with gcc


Clang currently rejects the following code:

template <typename X>
constexpr bool is_valid = true;

template<typename T>
class Nesting
{
public:
    template<typename Q> requires is_valid<Q>
    class Inner;
};


template<typename T>
template<typename Q> requires is_valid<Q>
class Nesting<T>::Inner 
{
public:
    static inline void Do();
};

#include <iostream>

template<typename T>
template<typename Q> requires is_valid<Q>
inline void Nesting<T>::Inner<Q>::Do()
{
    std::cout << sizeof(T);
}

int main() {
    Nesting<int>::Inner<bool>::Do();
}

with

<source>:14:31: error: requires clause differs in template redeclaration
   14 | template<typename Q> requires is_valid<Q>
      |                               ^
<source>:8:35: note: previous template declaration is here
    8 |     template<typename Q> requires is_valid<Q>
      |                                   ^
<source>:25:35: error: out-of-line definition of 'Do' from class 'Inner<Q>' without definition
   25 | inline void Nesting<T>::Inner<Q>::Do()
      |             ~~~~~~~~~~~~~~~~~~~~~~^
<source>:31:19: error: implicit instantiation of undefined template 'Nesting<int>::Inner<bool>'
   31 |     Nesting<int>::Inner<bool>::Do();
      |                   ^
<source>:9:11: note: template is declared here
    9 |     class Inner;

What is wrong with my code - is it a clang bug?


Solution

  • LLVM team confirms that this is a compiler bug: see https://github.com/llvm/llvm-project/issues/145521