c++20 的部分新概念及代码

1 概念(concepts)

cpp 复制代码
#include <iostream>
#include <concepts>

template<typename T>
concept Integral = std::is_integral_v<T>;

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

int main() {
    std::cout << add(5, 3) << std::endl;  // 输出:8
    // std::cout << add(3.5, 2.7) << std::endl;  // 错误:不满足Integral概念的要求
    return 0;
}

定义了一个概念(Integral),用于限定模板参数必须是整数类型。然后,我们定义了一个模板函数add,它接受两个满足Integral概念的参数,并返回它们的和。在main函数中,我们展示了如何使用这个模板函数来执行整数相加操作,而当传递非整数类型参数时,编译器会产生错误,因为不满足概念的要求

2三路比较运算符(<=>)

cpp 复制代码
#include <compare>
#include <iostream>

struct Point {
    int x;
    int y;

    auto operator<=>(const Point&) const = default; // 默认实现三路比较运算符
};

int main() {
    Point p1 {3, 4};
    Point p2 {5, 2};

    auto result = p1 <=> p2;
    
    if (result == std::strong_ordering::equal) {
        std::cout << "p1 equals p2" << std::endl;
    } else if (result == std::strong_ordering::less) {
        std::cout << "p1 is less than p2" << std::endl;
    } else {
        std::cout << "p1 is greater than p2" << std::endl;
    }

    return 0;
}

我们定义了一个Point结构体,它有两个整数成员变量x和y。我们使用默认的operator<=>实现了三路比较运算符。在main函数中,我们创建了两个Point对象p1和p2,并比较它们的大小关系。根据比较结果,我们输出相应的消息。

使用三路比较运算符可以简化代码,并使得比较操作更加直观和易于理解。

3 初始化捕获扩展(init-capture extension)

允许在lambda表达式中使用初始化器列表来捕获变量。这使得在lambda表达式中可以方便地捕获并初始化变量,而不需要额外的类成员或者在捕获列表中使用引用捕获

cpp 复制代码
#include <iostream>

int main() {
    int x = 5;
    int y = 10;

    auto lambda = [x = x + 1, &y = y]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };

    x = 100;
    y = 200;

    lambda(); // 输出:x: 6, y: 200

    return 0;
}

创建了一个lambda表达式lambda,它通过初始化捕获方式捕获了变量xyx通过值捕获,并在捕获时增加了1,而y则通过引用捕获。在lambda表达式中,我们输出了捕获的变量xy的值。即使在lambda表达式创建后,我们修改了原始变量xy的值,但是lambda表达式中捕获的值仍然保持了捕获时的状态。

初始化捕获扩展使得lambda表达式更加灵活,并且可以更方便地控制捕获的变量的初始化过程

4 协程(coroutines)

它是一种轻量级的线程,可以暂停和恢复执行,而不会阻塞整个线程。使用协程可以方便地实现异步编程,简化了复杂的异步代码

cpp 复制代码
#include <iostream>
#include <coroutine>

struct Generator {
    struct promise_type {
        int current_value;

        auto initial_suspend() {
            return std::suspend_always{};
        }

        auto final_suspend() noexcept {
            return std::suspend_always{};
        }

        Generator get_return_object() {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }

        void return_void() {}

        auto yield_value(int value) {
            current_value = value;
            return std::suspend_always{};
        }

        void unhandled_exception() {
            std::terminate();
        }
    };

    std::coroutine_handle<promise_type> coroutine;

    explicit Generator(std::coroutine_handle<promise_type> coro) : coroutine(coro) {}

    ~Generator() {
        if (coroutine) {
            coroutine.destroy();
        }
    }

    bool move_next() {
        coroutine.resume();
        return !coroutine.done();
    }

    int current_value() const {
        return coroutine.promise().current_value;
    }
};

Generator generate_range(int from, int to) {
    for (int i = from; i <= to; ++i) {
        co_yield i;
    }
}

int main() {
    auto generator = generate_range(1, 5);
    while (generator.move_next()) {
        std::cout << generator.current_value() << std::endl;
    }
    return 0;
}

定义了一个生成器Generator,它通过协程来生成一个指定范围内的整数序列。generate_range函数是一个协程函数,它使用co_yield语句来产生序列中的每个值。在main函数中,我们使用生成器来生成并输出从1到5的整数序列。

协程提供了一种简单而强大的方式来实现异步编程,使得代码更具可读性和可维护性。

相关推荐
xw-pp6 分钟前
回溯法的小结与概述
java·数据结构·c++·python·算法·递归
每天努力进步!34 分钟前
LeetCode热题100刷题6:160. 相交链表、206. 反转链表、234. 回文链表、141. 环形链表、142. 环形链表 II
c++·算法·leetcode·链表
weixin_4327027643 分钟前
统计信号处理基础 习题解答11-1
算法·信号处理
爱编程的Tom1 小时前
Map && Set(Java篇详解)
java·开发语言·数据结构·学习·算法
JokerSZ.2 小时前
【Leetcode 每日一题】268. 丢失的数字
数据结构·算法·leetcode
阿龍17872 小时前
Qt中udp指令,大小端,帧头帧尾实际示例
网络·c++·qt·网络协议·udp
㣲信团队2 小时前
小和问题和逆序对问题
数据结构·算法
muyierfly3 小时前
DAY19-力扣刷题
数据结构·算法·leetcode
Li&ShuaiShuai3 小时前
Linux系统编程:信号
linux·运维·服务器·c++·信号