【问题标题】:Disjunctions in a Concept requirement概念要求中的析取
【发布时间】:2019-01-19 08:35:46
【问题描述】:

requires expression 通常类似于:requires ( parameter-list(optional) ) { requirement-seq }

是否可以在不使用requires constraint-expr 的情况下在序列中形成析取(||)作为要求。例如:

template<typename T> concept FooBarExpert = 
requires(T a, T b) { 
    {a.foo(b)} || {a.bar(b)}; // Req 1
    { a.baz() }; // Req 2
    // and onward
}; 

【问题讨论】:

    标签: c++ c++-concepts c++20


    【解决方案1】:

    通过temp.constr.normal 中描述的称为约束规范化 的过程结合和分离原子约束 来分解概念。

    仅:

    • 逻辑和 &amp;&amp;,
    • 逻辑或 ||,
    • 括号表达式 ()
    • C&lt;A1, A2, ..., An&gt; 形式的 id 表达式,其中 C 命名一个概念

    被分解。所有其他表达式都是原子约束

    因此,require-expression 总体上是一个原子约束。在概念 TS 中,require-expression 被分解了,但在 C++20 中它们不是。 据我记得,我只是阅读了 c++ 委员会与概念相关的所有论文,原因是 require-expression 规范化可能会导致复杂性爆炸,从而降低编译速度。

    所以:

    requires(T a, T b) { 
        requires requires(T a, T b){a.foo(b)} 
              || requires(T a, T b){a.bar(b)}; // Req 1
        { a.baz() }; // Req 2
        // and onward
    }; 
    

    是一个原子约束。和

      requires(T a, T b) { 
        {a.foo(b)} 
        { a.baz() }; // Req 2
         // and onward
        }
    || requires(T a, T b) { 
         {a.bar(b)} 
         { a.baz() }; // Req 2
          // and onward
         };
    

    是两个原子约束的析取。 (这两个requires-expression

    最后:

         ( requires(T a, T b) { a.foo(b); } || requires (T a, T b) { a.bar(b); } )
      && requires(T a, T b) { a.baz(); /* and onward */};
    

    是析取与原子约束的合取。

    【讨论】:

    • 你能提供一个相同的参考吗?另外,实验性的clang fork没有实现C++20的概念方式(缺少一些简洁的语法),因为里面的连词需要做编译:concepts.godbolt.org/z/Qqxn3G
    • @tangy 据我所知,clang 版本是在 c++20 中的概念合并之前宣布的。 p0587r0 中给出了 requires 表达式不被分解的原因。 您能提供相同的参考吗?
    • 作为参考,我的意思是一些链接(正如你刚刚提供的:))到一个页面/文档,描述你作为 C++20 的一部分编写的内容。在链接的文档中说,此示例在requires expression 子主题下提供:template&lt;typename T&gt; concept bool X = requires (int x) { {f(x)} -&gt; T*; {f(x)} -&gt; C*; }
    • @tangy 它已经在那里了!第一句话,最后一个字,temp.constr.normal就是你要找的链接!
    • @tanguy 我进行了编辑。我希望现在不要那么混乱了。
    【解决方案2】:

    FooBarExpert 定义为适当的 requires 表达式的合取(或析取)。

    template<typename T> concept bool FooBarExpert =
    ( requires(T a, T b) {
        { a.foo(b) };
      } ||
      requires(T a, T b) {
        { a.bar(b) };
      }
    ) &&
    requires(T a, T b) {
      { a.baz() };
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      相关资源
      最近更新 更多