应该急切地还是懒惰地评估C++约束?
这个问题的主要目的是提请社区注意 libstdc++ 范围不适用于 clang:https ://bugs.llvm.org/show_bug.cgi ? id = 46746
Avi Kivity 建议这是一个 gcc 错误:https ://gcc.gnu.org/bugzilla/show_bug.cgi?id=97120
但随后他也暗示这是一个叮当声错误:https ://bugs.llvm.org/show_bug.cgi ? id = 47509
Rafael Ávila de Espíndola 将问题归结为以下代码,该代码使用 gcc 编译,但不使用 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> {};
叮当抱怨(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>())> {}
^~~~~~~~~~~~~~~~~~~~~~~~
那么问题来了,谁是对的?这段代码应该编译还是不编译?
还有一个更有趣的问题:我们可以用 clang 设置工作范围吗?
回答
[temp.inst]/17 :
模板特化或成员函数的类型约束和要求子句不会与特化或函数本身一起实例化,即使对于局部类的成员函数也是如此;在确定是否满足约束时或按照 [temp.constr.decl] 中指定的比较声明时,按照 [temp.constr.decl] 和 [temp.constr.atomic] 中指定的方式替换由它们形成的原子约束.
叮当虫。