Does a class template's requires clause have to be repeated outside member definitions?

你离开我真会死。 提交于 2021-01-27 06:57:26

问题


When the member of a class template that uses the requires clause is defined outside the class, gcc does not complain if requires is not specified, whereas clang does.

Consider the code snippet below:

#include <concepts>

template<typename Container>
    requires std::integral<typename Container::value_type>
class Foo {
public:
    void func();
};

template<typename Container>
void Foo<Container>::func()
{}

The compilation using gcc does not complain.

While clang reports the following error:

❯ clang++ -std=c++2a test.cpp
test.cpp:10:1: error: requires clause differs in template redeclaration
template<typename Container>
^
test.cpp:4:19: note: previous template declaration is here
    requires std::integral<typename Container::value_type>
                  ^
1 error generated.

If I change the definition as below:

template<typename Container>
    requires std::integral<typename Container::value_type>
void Foo<Container>::func()
{}

now clang does not complain.

Output from gcc --version:

gcc (GCC) 10.2.0

Output from clang --version:

clang version 10.0.1 
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Is this a bug to be reported?


回答1:


A bug should be filed for GCC, because it accepts the code, even though the declaration of the member outside the class does not have an equivalent template-head.

[temp.class]

3 When a member function, a member class, a member enumeration, a static data member or a member template of a class template is defined outside of the class template definition, the member definition is defined as a template definition in which the template-head is equivalent to that of the class template ([temp.over.link]).

[temp.over.link]

6 Two template-heads are equivalent if their template-parameter-lists have the same length, corresponding template-parameters are equivalent and are both declared with type-constraints that are equivalent if either template-parameter is declared with a type-constraint, and if either template-head has a requires-clause, they both have requires-clauses and the corresponding constraint-expressions are equivalent.

The equivalence of templates-heads requires that both have an equivalent requires clause. Omitting it entirely breaks the equivalence.




回答2:


From [temp.mem.func]/1 [extract, emphasis mine]:

A member function of a class template may be defined outside of the class template definition in which it is declared. [Example:

A constrained member function can be defined out of line:

template<typename T> concept C = requires {
  typename T::type;
};

template<typename T> struct S {
  void f() requires C<T>;
  void g() requires C<T>;
};

template<typename T>
  void S<T>::f() requires C<T> { }  // OK
template<typename T>
  void S<T>::g() { }                // error: no matching function in S<T>

end example]

taking note particularly the final example of the (non-normative) text.

Thus, Clang is correct to reject whereas GCC is wrong to accept the first program as the out-of-line definition

template<typename Container>
void Foo<Container>::func() {}

does not match any function in Foo<Container>.

(I have not yet found an open GCC bug report for this)



来源:https://stackoverflow.com/questions/63628752/does-a-class-templates-requires-clause-have-to-be-repeated-outside-member-defin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!