【问题标题】:Should c++ constraints be evaluated eagerly or lazily?应该急切地或懒惰地评估 c++ 约束吗?
【发布时间】:2021-06-24 15:23:37
【问题描述】:

这个问题的主要目的是提请社区注意 libstdc++ 范围不适用于 clang:https://bugs.llvm.org/show_bug.cgi?id=46746

Avi Kivity 建议这是一个 gcc 错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97120

但随后他也暗示这是一个clang错误: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> {};

clang 抱怨 (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 提供工作范围?

【问题讨论】:

  • 问“谁是对的?”需要参考标准,这使得这是一个语言律师问题。只有 5 个标签意味着我必须选择其他标签来删除,而编译器标签似乎是最好的选择。如果你愿意,可以随意编辑标签,但是 [c++] 和 [language-lawyer] 应该在那里。
  • 一般来说,我不确定 SO Question 是否是“将社区的注意力吸引到不适用于 clang 的 libstdc++ 范围”的最佳方式。
  • @SergeyA:SO 上有很多人非常熟悉 C++ 标准,其中包括不少作者。
  • @MSalters 我对此并不感到惊讶,我很清楚这一事实。但是,我不确定这些人是否积极监控问题队列。我相信,有专门的小组,这样的信息会更明显。
  • 我希望 SFINAE 不适用于 requires 子句。它不是必需的(你可以用 SFINAE 做的所有事情都可以在 requires 子句中做),而且它在概念上很复杂。此外,“有一个成员”要求不应该仅仅因为有人调用它就出现硬错误,这使得审计要求条款变得很痛苦。所以我希望 clang 是对的。

标签: c++ language-lawyer c++-concepts std-ranges


【解决方案1】:

[temp.inst]/17:

模板的type-constraintsrequires-clause 特化或成员函数不与 特化或函数本身,即使对于 a 的成员函数 本地班;代入由它们形成的原子约束 而是按照 [temp.constr.decl] 中的指定执行,并且 [temp.constr.atomic] 确定约束是否为 比较时满足或在 [temp.constr.decl] 中指定 声明。

Clang 错误。

【讨论】:

    【解决方案2】:

    按照 T.C. 的回答中的链接,我在标准中找到了一个相关示例,即 clang 拒绝编译。这清楚地表明了 clang 中的错误。

    [temp.constr.decl]/4:

    template <class T> concept C = true;
    template <class T> struct A {
      template <class U> U f(U) requires C<typename T::type>;   // #1
      template <class U> U f(U) requires C<T>;                  // #2
    };
    
    template <> template <class U>
    U A<int>::f(U u) requires C<int> { return u; }              // OK, specializes #2
    

    clang output:

    <source>:3:49: error: type 'int' cannot be used prior to '::' because it has no members
      template <class U> U f(U) requires C<typename T::type>;   // #1
                                                    ^
    

    我为此创建了一个专门的错误:https://bugs.llvm.org/show_bug.cgi?id=50864

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 2012-03-05
      • 2016-05-12
      • 2014-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多