代码之家  ›  专栏  ›  技术社区  ›  Chan Kha Vu

C++20:多类型及其约束的概念,正确的语法?

  •  2
  • Chan Kha Vu  · 技术社区  · 6 年前

    据证实,在即将到来的 c++20 标准,根据 this reddit report 从最近 Cologne ISO C++ Meeting ,我们将能够指定模板的 concept 对于每个类/函数模板,我们将能够设置 constraints 关于它的类型。但是,在文档和教程中(例如 here ),我找不到多类型用例的正确语法。


    假设我们有一个多类型的概念:

    template<typename T1, typename T2>
    concept AreEqComparable = requires(T1 a, T2 b) {
        { a == b } -> bool;
    };
    

    比方说,我想在两种不同类型之间定义一个简单的比较函数。 我怎样才能做到呢? 更具体地说,我应该在 ??? 部分代码如下:

    ???
    bool are_equal(T1 a, T2 b) { return a == b; }
    

    我找不到任何关于这个案子的线索 在这里 我是说, here ,甚至 here 是的。我随机试过类似的方法:

    /* 1 */ template<AreEqComparable T1, T2>
    /* 2 */ AreEqComparable<T1, T2>
    /* 3 */ template<AreEqComparable<T1, T2>>
    

    但它们都会抛出语法错误。我想答案应该在说明书的某个地方 P0557 Bjarne Stroustrup ,但我看了一眼就找不到了。

    1 回复  |  直到 5 年前
        1
  •  14
  •   L. F.    6 年前

    你可以这样写:

    template <typename T1, typename T2>
        requires AreEqComparable<T1, T2>
    bool are_equal(T1 a, T2 b)
    {
        // ...
    }
    

    在这里,我们使用 Requires子句 对类型模板参数施加要求。

        2
  •  10
  •   Barry    6 年前

    你可以写:

    template <typename T1, AreEqComparable<T1> T2>
    bool are_equal(T1, T2);
    

    这相当于:

    template <typename T1, typename T2>
        requires AreEqComparable<T2, T1>
    bool are_equal(T1, T2);
    

    类型在这里的约束中翻转, AreEqComparable<T2, T1> 而不是 AreEqComparable<T1, T2> 是的。这当然对许多概念都很重要,但可能不是特别重要,因为 == 它本身在c++20中变得对称(缺少病理病例,这些病例不应该存在于实际代码中)。如果你想成为 真的? 确保这种对称性是有效的,您可以在概念中始终使其明确(如 EqualityComparableWith 在工作草案中):

    template<typename T1, typename T2>
    concept AreEqComparable = requires(T1 a, T2 b) {
        { a == b } -> bool;
        { b == a } -> bool;
    };
    

    通过翻转模板参数的顺序(h/t matthieu m.),实际上可以按正确的顺序获得所需的约束:

    template <typename T2, AreEqComparable<T2> T1>
    bool are_equal(T1, T2);
    
        3
  •  4
  •   Davis Herring    6 年前

    另一种完全避免引入模板参数的语法(以增加其他冗余为代价):

    bool are_equal(auto x,auto y)
      requires AreEqComparable<decltype(x),decltype(y)>
      {return x==y;}
    
        4
  •  4
  •   jerry_fuyi    5 年前

    在GCC 8.2.0中,概念应写成:

    concept bool ConceptName = /* ... */
    

    但是 C++ Templates: The Complete Guide 没有提到 bool 是的。由于c++20标准没有发布,很难说哪个是正确的。

    对于需要一个参数(不一定是类型)的概念,有一个速记:

    template <UnaryConceptName T>
    

    对于那些需要两个或更多参数的人,没有速记:

    template <typename T1, typename T2> requires BinaryConceptName<T1, T2>
    

    typename 可以替换为特定类型名。

    顺便说一句:

    1. 我上面提到的这本书对概念作了简要的介绍。

    2. 使用 -fconcepts 在gcc中启用概念。