#include <concepts>
#include <iostream>
class BaseClass {
public:
int getValue() const {
return 1;
}
};
class DerivedClass: public BaseClass {
public:
int getValue() const {
return 2;
}
};
class NonDerivedClass {
public:
int getValue() const {
return 3;
}
};
template<class T>
concept DerivedOfBaseClass = std::is_base_of_v<BaseClass, T>;
template <DerivedOfBaseClass T>
void doGetValue(const T& a) {
std::cout << "Get value:" << a.getValue() << std::endl;
}
int c2() {
DerivedClass d;
doGetValue(d);
BaseClass b;
doGetValue(b);
// 解除注释会引发错误
// NonDerivedClass n;
// doGetValue(n);
return 0;
}
int main() {
c2();
return 0;
}
template<typename T>
constexpr bool get_value() { return T::value; }
template<typename T>
requires (sizeof(T) > 1 && get_value<T>())
void f(T) {
std::cout << "template version" << std::endl;
}
void f(int32_t) {
std::cout << "int version" << std::endl;
}
void c15() {
f('A');
}
&&:
template<class T>
concept Integral = std::is_integral_v<T>;
template<class T>
concept SignedIntegral = Integral<T> && std::is_signed_v<T>;
template<class T>
concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
||:
template <class T>
concept Integral = std::is_integral_v<T>;
template <class T>
concept FloatingPoint = std::is_floating_point_v<T>;
template <class T>
concept Number = Integral<T> || FloatingPoint<T>;
原子约束:
template <class T>
concept Floating = std::is_floating_point_v<T>;
template <class T>
concept BadNumber = std::is_floating_point_v<T> && std::is_floating_point_v<T>;
template <class T>
concept Number = Floating<T> && std::is_floating_point_v<T>;
template <Floating T> // #1
void func(T) {}
template <BadNumber T> // #2
void func(T) {}
template <Number T> // #3
void func(T) {}
原子约束,由表达式 E 与 E 的参数映射组成。参数映射指的是 E 中受约束实体的模板参数(template parameter)与实例化时使用的模板实参(template argument)之间的映射关系。
E 的值必须是 bool 类型,不允许通过任何隐式转换变为 bool 型。
编译器在实例化过程中,会检查参数是否满足原子约束。编译器会根据参数映射关系,将模板实参替换成表达式 E 中的形参。
如果替换后的表达式是一个非法类型或者非法表达式,说明当前实例化参数不满足约束
requires 与普通约束表达式不同,如果其定义体在完成参数替换后,存在非法的类型或表达式,或者 requires 定义中的约束存在冲突时,会返回 false。反之,如果完成参数替换后语法检查以及约束检查全部成功之后,才会返回 true。
template<typename T>
concept Histogram = requires(T h1, T h2) {
h1.getMoments(); // 要求有getMoments接口
T::count; // 要求有静态变量count
h1.moments; // 要求有成员变量moments
h1 + h2; // 要求对象能够进行+操作
typename T::type; // 要求存在类型成员type
typename std::vector<T>; // 要求能够模板实例化并与std::vector组合使用
{ h1.getSubHistogram() } -> same_as<T>; // 要求接口返回类型与T一致
{ h1.getUnit() } -> convertible_to<float>; // 要求接口返回类型能转换成float,本质上接口返回类型可能是double
{ h1 = std::move(h2) } noexcept; // 要求表达式不能抛出异常
requires sizeof(T) > 4;
};
requires子句:
requires 子句存在的意义是判断它所约束的声明在“上下文”中是否可行
export template <typename T1, typename T2>
requires requires (T1 x, T2 y) { x + y; }
std::common_type<T1, T2> func(
T1 arg1, T2 arg2
) {
return arg1 + arg2;
}