C++ 这是一个带有C++;20个概念,还是我做错了什么?

C++ 这是一个带有C++;20个概念,还是我做错了什么?,c++,gcc,c++20,c++-concepts,C++,Gcc,C++20,C++ Concepts,我正在试验C++20的概念,使用我自己本地构建的GCC11源代码的克隆。我从GCC中得到了编译错误,这对我来说似乎是错误的。我已经将触发诊断的代码减少到下面的内容,使用GCC命令行编译它,并在下面生成完整的诊断输出 对于focus,我认为错误的诊断输出的特定部分是 repro.cpp:9:13: note: the required expression ‘flequal(a, b)’ is invalid, because 9 | {flequal(a, b)} -> s

我正在试验C++20的概念,使用我自己本地构建的GCC11源代码的克隆。我从GCC中得到了编译错误,这对我来说似乎是错误的。我已经将触发诊断的代码减少到下面的内容,使用GCC命令行编译它,并在下面生成完整的诊断输出

对于focus,我认为错误的诊断输出的特定部分是

repro.cpp:9:13: note: the required expression ‘flequal(a, b)’ is invalid, because
    9 |     {flequal(a, b)} -> std::convertible_to<bool>;
      |      ~~~~~~~^~~~~~
repro.cpp:9:13: error: ‘flequal’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
repro.cpp:22:6: note: ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&)’ declared here, later in the translation unit
   22 | bool flequal(Bar<Flequalable auto> const &a, Bar<Flequalable auto> const &b) {
      |      ^~~~~~~
完整GCC诊断:

repro.cpp: In function ‘bool foo()’:
repro.cpp:29:24: error: no matching function for call to ‘flequal(Bar<double>&, Bar<double>&)’
   29 |     return flequal(a, b); // Causes diagnostic
      |                        ^
repro.cpp:13:6: note: candidate: ‘template<class T>  requires  floating_point<T> bool flequal(T, T)’
   13 | bool flequal( T a, T b) {
      |      ^~~~~~~
repro.cpp:13:6: note:   template argument deduction/substitution failed:
repro.cpp:13:6: note: constraints not satisfied
In file included from repro.cpp:1:
/usr/local/gcc-11-master/include/c++/11.0.1/concepts: In substitution of ‘template<class T>  requires  floating_point<T> bool flequal(T, T) [with T = Bar<double>]’:
repro.cpp:29:24:   required from here
/usr/local/gcc-11-master/include/c++/11.0.1/concepts:111:13:   required for the satisfaction of ‘floating_point<T>’ [with T = Bar<double>]
/usr/local/gcc-11-master/include/c++/11.0.1/concepts:111:30: note: the expression ‘is_floating_point_v<_Tp> [with _Tp = Bar<double>]’ evaluated to ‘false’
  111 |     concept floating_point = is_floating_point_v<_Tp>;
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:22:6: note: candidate: ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&)’
   22 | bool flequal(Bar<Flequalable auto> const &a, Bar<Flequalable auto> const &b) {
      |      ^~~~~~~
repro.cpp:22:6: note:   template argument deduction/substitution failed:
repro.cpp:22:6: note: constraints not satisfied
repro.cpp: In substitution of ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&) [with auto:1 = double; auto:2 = double]’:
repro.cpp:29:24:   required from here
repro.cpp:6:9:   required for the satisfaction of ‘Flequalable<auto:1>’ [with auto:1 = double]
repro.cpp:8:8:   in requirements with ‘T a’, ‘T b’ [with T = double]
repro.cpp:9:13: note: the required expression ‘flequal(a, b)’ is invalid, because
    9 |     {flequal(a, b)} -> std::convertible_to<bool>;
      |      ~~~~~~~^~~~~~
repro.cpp:9:13: error: ‘flequal’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
repro.cpp:22:6: note: ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&)’ declared here, later in the translation unit
   22 | bool flequal(Bar<Flequalable auto> const &a, Bar<Flequalable auto> const &b) {
      |      ^~~~~~~

首先,
Bar
是无效语法。可以将顶级变量声明为
Concept auto v
,但不能将其嵌套在模板中。所以它真的应该是:

模板
布尔·弗莱夸尔(律师事务所和律师事务所、律师事务所和律师事务所){
返回true;
}
现在,当我们尝试调用
flequal(a,b)
时会发生什么。我们推导出
T=double
U=double
,然后尝试评估
double
是否满足
Flequalable
double
浮点
,因此我们继续检查
flequal(a,b)
是两个
double
s的有效表达式的要求

这是非限定查找,因此我们首先对名称
flequal
执行常规非限定查找。重要的是要记住,这种查找是从概念定义的角度进行的,而不是从使用的角度。也就是说,我们从这里向上看:

#包括
使用std::浮点;
模板
概念可扩展
=浮点
&&需要(T a,T b){
{flequal(a,b)}->std::convertible_to;//首先,
Bar
是无效语法。您可以将顶级变量声明为
Concept auto v
,但不能将其嵌套在模板中。因此它实际上应该是:

模板
布尔·弗莱夸尔(律师事务所和律师事务所、律师事务所和律师事务所){
返回true;
}
现在,当我们试图调用
flequal(a,b)
时会发生什么?我们推导
T=double
U=double
,然后尝试评估
double
是否满足
Flequalable
double
浮点值,因此我们继续检查
flequal(a,b)的要求
是两个
double
s的有效表达式

这是非限定查找,因此我们首先对名称
flequal
执行常规非限定查找。请记住,此查找是从概念定义的角度进行的,而不是从使用它的位置进行的。也就是说,我们从这里开始查找:

#包括
使用std::浮点;
模板
概念可扩展
=浮点
&&需要(T a,T b){

{flequal(a,b)}->std::convertive_to;//实例化点是一个棘手的概念。在这种情况下,您和编译器对它的位置似乎有不同的想法。实例化点是一个棘手的概念。在这种情况下,您和编译器对它的位置似乎有不同的想法。我认为如果您更明确一点,将有助于避免混淆我们为
flequal
执行的非限定名称查找发生在概念定义的上下文中,而不是函数模板定义的上下文中,甚至是
main
中调用站点的上下文中。事实上,这可能是一种罕见的情况,它可以帮助用户更好地理解我发现在编译模板定义时实际上会出现不合格的名称查找。我开始发表评论,询问我的困惑是否是我希望在foo()中调用“fequal(a,b)”的地方检查概念需求,所以当诊断说“需求失败,因为flequal(double,double)直到后来在eh translation unit中才出现”。不合格的查找是否意味着在实际定义概念需求时,还没有任何flequal(double,double)声明?至于flequal是否是一个定制点,我不确定它是否符合定制点的真正含义。由于这里的代码是一个最小化的示例,用于触发诊断,结合了头和.cpp,它可能无法传达意图。但我对flequal的计划是为了找到一种比较浮点数的方法,如以及任何更大的类,它们的比较最终会归结为浮点比较。在我看来,flequal是一个项目范围的操作,对于定义了它们的新类,它将被重载。@Barry,当我将定义替换为
概念Flequalable
模板bool flequal(T,T)
,它将按照您所说的那样构建。但GCC随后接受了
bool-flequal(Bar-const&a,Bar-const&b)
,你说这是无效的语法。那么这是GCC错误吗?如果我删除
自动
,但不添加序言
模板,我想如果你更明确一点,我们为
flequal
执行的非限定名称查找是在概念定义的上下文中发生的,而不是在co中,这将有助于避免混淆函数模板定义的文本,甚至是
main
中调用站点的上下文。事实上,如果我们指出编译模板定义时实际上会出现不合格的名称查找,这可能是其中一种罕见的情况,它可能会帮助用户更好地理解。我已经开始发表评论,询问我的困惑是否会消失因为我希望在foo()中调用“fequal(a,b)”时检查概念需求,所以当诊断说“需求失败,因为flequal(double,double)直到后来在eh翻译单元中才出现”时,我感到困惑.不合格查找是否意味着在实际定义概念要求时,还没有任何flequal(双精度,双精度)声明
/usr/local/gcc-11-master/bin/g++-11 -c repro.cpp -o repro.o -std=c++20 -fconcepts-diagnostics-depth=5 2> diagnostic.txt
repro.cpp: In function ‘bool foo()’:
repro.cpp:29:24: error: no matching function for call to ‘flequal(Bar<double>&, Bar<double>&)’
   29 |     return flequal(a, b); // Causes diagnostic
      |                        ^
repro.cpp:13:6: note: candidate: ‘template<class T>  requires  floating_point<T> bool flequal(T, T)’
   13 | bool flequal( T a, T b) {
      |      ^~~~~~~
repro.cpp:13:6: note:   template argument deduction/substitution failed:
repro.cpp:13:6: note: constraints not satisfied
In file included from repro.cpp:1:
/usr/local/gcc-11-master/include/c++/11.0.1/concepts: In substitution of ‘template<class T>  requires  floating_point<T> bool flequal(T, T) [with T = Bar<double>]’:
repro.cpp:29:24:   required from here
/usr/local/gcc-11-master/include/c++/11.0.1/concepts:111:13:   required for the satisfaction of ‘floating_point<T>’ [with T = Bar<double>]
/usr/local/gcc-11-master/include/c++/11.0.1/concepts:111:30: note: the expression ‘is_floating_point_v<_Tp> [with _Tp = Bar<double>]’ evaluated to ‘false’
  111 |     concept floating_point = is_floating_point_v<_Tp>;
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:22:6: note: candidate: ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&)’
   22 | bool flequal(Bar<Flequalable auto> const &a, Bar<Flequalable auto> const &b) {
      |      ^~~~~~~
repro.cpp:22:6: note:   template argument deduction/substitution failed:
repro.cpp:22:6: note: constraints not satisfied
repro.cpp: In substitution of ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&) [with auto:1 = double; auto:2 = double]’:
repro.cpp:29:24:   required from here
repro.cpp:6:9:   required for the satisfaction of ‘Flequalable<auto:1>’ [with auto:1 = double]
repro.cpp:8:8:   in requirements with ‘T a’, ‘T b’ [with T = double]
repro.cpp:9:13: note: the required expression ‘flequal(a, b)’ is invalid, because
    9 |     {flequal(a, b)} -> std::convertible_to<bool>;
      |      ~~~~~~~^~~~~~
repro.cpp:9:13: error: ‘flequal’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
repro.cpp:22:6: note: ‘template<class auto:1, class auto:2>  requires (Flequalable<auto:1>) && (Flequalable<auto:2>) bool flequal(const Bar<auto:1>&, const Bar<auto:2>&)’ declared here, later in the translation unit
   22 | bool flequal(Bar<Flequalable auto> const &a, Bar<Flequalable auto> const &b) {
      |      ^~~~~~~

Using built-in specs.
COLLECT_GCC=/usr/local/gcc-11-master/bin/g++-11
COLLECT_LTO_WRAPPER=/usr/local/gcc-11-master/libexec/gcc/x86_64-pc-linux-gnu/11.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc/configure --prefix=/usr/local/gcc-11-master --program-suffix=-11 --enable-libstdcxx-debug : (reconfigured) ../gcc/configure --prefix=/usr/local/gcc-11-master --program-suffix=-11 --enable-libstdcxx-debug
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.0.1 20210304 (experimental) (GCC)