对于类模板、函数模板、非模板函数可以使用关联约束,这些具名合集称作概念(concept)。每个概念都是谓词,编译期求值(bool)。

template <typename T>
concept is_int = requires{ 
	{ T{} } -> std::same_as<int>; 
};

template <is_int T>
void fun(T a) {
}

在编译期对其进行检查。

int main(int argc, char* argv[]) {
	std::cout << std::boolalpha << is_int<int> << "\n";     // true
    std::cout << std::boolalpha << is_int<double> << "\n";  // false
    
     return 0;
}

概念

定义

概念是要求的具名集合。概念的定义必须在命名空间作用域中出现。

概念定义拥有以下形式:

template < 模板形参列表 >
concept 概念名 = 约束表达式;

概念不能递归,也不能受约束。

例子

看一个标准库中的概念(MSVC 14.3), std::same_as 的实现。

template <class _Ty1, class _Ty2>
concept _Same_impl = 
    is_same_v<_Ty1, _Ty2>;

template <class _Ty1, class _Ty2>
concept same_as = _Same_impl<_Ty1, _Ty2> && _Same_impl<_Ty2, _Ty1>;

same_as 使用了 std::is_same_v 实现,用于比较两个类型是否完全一致。

std::cout << std::boolalpha << std::same_as<int, int> << "\n";    // true
std::cout << std::boolalpha << std::same_as<double, int> << "\n"; // false
std::cout << std::boolalpha << std::same_as<int&, int> << "\n";   // false
std::cout << std::boolalpha << std::same_as<int*, int> << "\n";  // false

测试代码
测试代码运行结果
结果符合预期。
具体分析 std::same_as填坑 (还没写,待填坑)。

特点
  • 概念不能被显式实例化、显式特化或部分特化(不能更改约束的原初定义的含义)。
  • 概念可以在标识表达式中命名。该标识表达式的值在满足约束表达式时是 true,否则是 false
  • 概念在“类型约束”中接受的实参要比它的形参列表要求的要少一个,因为按语境推导出的类型会隐式地用作第一个实参。
template <std::same_as<int> T>
constexpr bool is_int_t = false;

会推导出 std::same_as<T, int> ,可以少写一个参数。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐