我如何定义这个 C++ 约束?

问题描述

我有两种类型 AA_InputAA_Input 构造而成。

我想定义一个模板类 B,它有两个模板参数,TU。然后我想为 B 定义一个约束,它要求 T一个接受 U 的构造函数

我尝试编写这样的 B 如下:

template<typename T,typename U>
requires requires (U u) {
    T::T(u);
}
class B {
public:
    B(){}
    void speak() {
        std::cout << "success!";
    }
};

示例 Tclass A,隐含的 UA_Inputs,如下所示:

class A_Inputs {
public:
    A_Inputs(){}
};

class A {
public:
    A(A_Inputs ain){}
};

然后我使用以下 main 函数测试所有内容

int main() {
    B<A,A_Inputs> b{};
    b.speak();
    return 0;
}

这会给

error C7602: 'B': the associated constraints are not satisfied

解决方法

编写可构造性约束的方法是使用 constructible_from 概念:

template<typename T,typename U>
    requires std::constructible_from<T,U>
class B { ... };
,

您应该阅读整个错误消息,而不仅仅是其中的一行。

With gcc I get

<source>: In function 'int main()':
<source>:31:18: error: template constraint failure for 'template<class T,class U>  requires requires(U u) {(T::T)(u);} class B'
   31 |     B<A,A_Inputs> b{};
      |                  ^
<source>:31:18: note: constraints not satisfied
<source>: In substitution of 'template<class T,class U>  requires requires(U u) {(T::T)(u);} class B [with T = A; U = A_Inputs]':
<source>:31:18:   required from here
<source>:7:7:   required by the constraints of 'template<class T,class U>  requires requires(U u) {(T::T)(u);} class B'
<source>:4:10:   in requirements with 'U u' [with T = A; U = A_Inputs]
<source>:5:9: note: the required expression 'T::T(u)' is invalid
    5 |     T::T(u);
      |     ~~~~^~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
[...]

还有更多关于其他错误的信息,这些错误只是由于 B<A,A_Inputs> b{}; 不正确。这里的重要部分是 'T::T(u)' 无效。应该是T(u);

#include <iostream>

template<typename T,typename U>
requires requires (U u) {
    T(u);
}
class B {
public:
    B(){}
    void speak() {
        std::cout << "success!";
    }
};

class A_Inputs {
public:
    A_Inputs(){}
};

class A {
public:
    A(A_Inputs ain){}
};

class X {
    public:
    X() {}
};

int main() {
    B<A,A_Inputs> b{};
    b.speak();
    B<X,A_Inputs> x{};
}

这只会按预期为 B<X,A_Inputs> x{}; 产生错误,因为约束未满足。

,
template<class Src,class Dest>
concept can_construct  = requires(Src s){
  { Dest(std::forward<Src>(s)); }
}

template<typename T,can_construct<T> U>
class B

喜欢吗?

您应该寻求使用命名概念。这也让您可以为它们添加静态断言测试,以在更简单的上下文中捕获错误。

请注意,can_construct<T> U 需要 can_construct<U,T> - U 被“加前缀”到概念模板参数中。