前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++20 concepts

C++20 concepts

作者头像
程序员的园
发布2024-07-18 13:18:10
550
发布2024-07-18 13:18:10
举报
文章被收录于专栏:程序员的园——原创文章

如果知道我会死在哪里,那我将永远不去那个地方 -查理 芒格

定义

概念(concepts),作为模板元编程(类模板和函数模板)的一部分,提出对模板实参的要求,进而影响模板的特化和函数重载。在编译期对实参求值,检测实参是否满足概念所提出的要求。

由以上定义中“在编译期对实参求值,检测实参是否满足概念所提出的要求”可知concepts实则为可以在编译期进行求值的模板类型的bool型变量。

进而的,concepts作为编译期进行求值的bool型变量,则可以对其进行&&、||、!操作,即concepts可以是单个/多个条件的交集、并集、补集。

定义

代码语言:javascript
复制
template < 模板形参列表 >
concept 概念名 属性(可选) = 约束表达式;

使用示例

代码语言:javascript
复制
#include <concepts>

template <typename T>
concept my_integeral = std::integral<T>;

template<my_integeral  T>
T add(T a, T b)
{
  return a+b;
}

void using_concept()
{
  add(3,5);
  add(3.0, 5.0);//error
}

性质

概念不能递归地提及自身

代码语言:javascript
复制
template<typename T>
concept V = V<T*>; //V<T>要求V<T*>也为真。这种递归定义在C++的概念中是不被允许的,会导致编译错误。

template<V C>
C sub(C a, C b)
{
  return a-b;
}

概念不能有关联的约束

代码语言:javascript
复制
template<C1 T>
concept Error1 = true; //不能接受C1约束

template<class T> requires std::is_integral_v<T>
  concept Error2 = true; //不能接受requires约束

概念不能被显式实例化、显式特化或

部分特化

  1. 显式实例化:尝试为模板创建一个特定的类型实例。例如,对于一个模板类TemplateClass,我们可以尝试创建TemplateClass<int>的一个实例。
  2. 显式特化:为模板提供一个特定的类型版本。例如,我们可以为TemplateClass<int>提供一个特定的实现。
  3. 部分特化:为模板的某些类型参数提供特定的实现。例如,我们可以为TemplateClass<T, int>提供一个特定的实现。
代码语言:javascript
复制
template <typename T>  
concept bool MyConcept = /* ... */;  
  
// 以下都是错误的  
MyConcept<int> obj;  // 错误:概念不能被显式实例化  
template <>  
concept bool MyConcept<int> = /* ... */;  // 错误:概念不能被显式特化  
template <typename U>  
concept bool MyConcept<U, int> = /* ... */;  // 错误:概念不能被部分特化

概念可以在标识表达式中使用

该标识表达式的值在满足约束表达式时是 true,否则是 false

代码语言:javascript
复制
template <typename T>  
concept bool MyConcept = requires(T t) {  
    { t.foo() } -> std::same_as<void>;  
};  
  
int main() {  
    if constexpr (MyConcept<MyClass>) {  
        // MyClass满足MyConcept  
    } else {  
        // MyClass不满足MyConcept  
    }  
}

使用方法

常规使用方法

代码语言:javascript
复制
template <typename T>
concept SignedIntegral = std::is_integral_v<T> && std::is_signed_v<T>;

template <SignedIntegral T>
void f1(T v)
{

}

template <typename T>
    requires SignedIntegral<T>
void f2(T v)
{
    
}

template <typename T>
void f3(T v) requires SignedIntegral<T>
{

}

void f4(SignedIntegral auto v)
{

}

template <SignedIntegral auto v>
void g2()
{

}

lambda表达式中使用

代码语言:javascript
复制
auto f = []<SignedIntegral T> (T v) {
    // ...
};

auto f = []<typename T> requires SignedIntegral<T>(T v) {
    // ...
};

auto f = []<typename T> (T v) requires SignedIntegral<T> {
    // ...
};

auto f = [](SignedIntegral auto v) {
    // ...
    };

auto g = []<SignedIntegral auto v> () {
    // ...
};

参考文献:

https://zhuanlan.zhihu.com/p/266086040

Constraints and concepts (since C++20) - cppreference.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档