《STL源码分析》学习笔记 — C++20 concepts

本文详细讲解了C++20中的概念(concepts)及其定义,包括约束(constraints)的构造(并合、析取、原子约束等)、requires子句的使用、以及各种要求分类。通过实例演示了如何使用concepts确保模板参数的类型安全,以及在函数模板和类模板中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在C++20之前的版本,迭代器相关类型的获取都是通过我们前面学习过的 iterator_traits。这个结构比较好理解。在C++20及之后,C++中提供了两个新的关键字 conceptrequires 用于定义概念。

一、什么是concepts

在C++参考手册中,是这样描述概念的:

Class templates, function templates, and non-template functions (typically members of class templates) may be associated with a constraint, which specifies the requirements on template arguments, which can be used to select the most appropriate function overloads and template specializations.
Named sets of such requirements are called concepts. Each concept is a predicate, evaluated at compile time, and becomes a part of the interface of a template where it is used as a constraint

类模板、函数模板、非模板方法(特指类模板中的方法)可能会与某个约束相关联,用以特化对模板参数的要求。这可以被用来选择最合适的函数重载和模板特化。

这样的具名要求集合被称为概念。每个概念是一个断言,在编译时评估,而且该概念作为限制使用的模板的一部分。因此 concept 的违反将在编译时被检测到:

std::list<int> l = {
   3,-1,10};
std::sort(l.begin(), l.end()); 
//Typical compiler diagnostic without concepts:
//  invalid operands to binary expression ('std::_List_iterator<int>' and
//  'std::_List_iterator<int>')
//                           std::__lg(__last - __first) * 2);
//                                     ~~~~~~ ^ ~~~~~~~
// ... 50 lines of output ...
//
//Typical compiler diagnostic with concepts:
//  error: cannot call std::sort with std::_List_iterator<int>
//  note:  concept RandomAccessIterator<std::_List_iterator<int>> was not satisfied

上述代码中 sort 算法需要的迭代器为随机访问迭代器,因此编译无法通过。

二、concepts 的定义

使用 concept 关键字的语法为:

template < template-parameter-list >
concept concept-name = constraint-expression;

如:

template <class T, class U>
concept Derived = std::is_base_of<U, T>::value;

concept 不能递归依赖自身,其模板参数也不能使用约束。除此之外,concept 的显式实例化、显式特化、部分特化都是不支持的。

concept 可以被用于 id 表达式中。当其限制被满足时,表达式为真;否则, 表达式为假:

#include <iostream>

template<typename T>
concept dereferenceable = requires (T a) 
{
   
	*a;
};

int main()
{
   
	constexpr bool bl1 = dereferenceable<int>;
	std::cout << bl1 << std::endl;
	
	constexpr bool bl2 = dereferenceable<int*>;
	std::cout << bl2 << std::endl;
}

在这里插入图片描述

concept 还能被用于类型限制中,作为类型模板参数声明占位类型说明符 以及复合要求中。其中,concept 被用于占位类型说明符主要是用于约束推导的类型:

#include <iostream>

template<typename T>
concept dereferenceable = requires (T a) 
{
   
	*a;
};

int main()
{
   
	int a = 1;
	auto b = a;
	dereferenceable auto c = a; //invalid,int 不满足 dereferenceable
	dereferenceable auto d = &a;
}

三、constraints

一个约束是一系列特化了模板参数要求的操作及操作数。它们可以直接出现在 requires 表达式中并且直接作为 concept 的一部分。

1、Conjunctions

我们可以使用 && 连接两个约束,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值