当前位置: 首页 > article >正文

C++20 STL CookBook2 更强大的编译时 + 安全比较 + spaceship比较符

目录

使用编译时vector和字符串相关的上下文变量

安全的比较整数

<=> :)


使用编译时vector和字符串相关的上下文变量

在大部分C语言程序中,我见过不少人是这样使用常量字符串的:

#define STR "Hello, C++"

然后可能传递进入一些函数做一些可能跟字符串本身存储字符无关的运算。但是C++中,除非控制编译流程,实在不建议使用宏。那有没有代替品呢?有!我们可以使用一些编译时就可以确定的东西传递:

#include <iostream>
static constexpr const char* ready_calc = "string";
constexpr size_t gain_const_string() {
    return std::string(ready_calc).size();
}

或者:

constexpr auto check_sum(){
    std::vector<int> vec{1, 2, 3, 4, 5};
    return std::accumulate(std::begin(vec), std::end(vec), 0);
}

constexpr 说明符声明可在编译时求值的变量或函数。在 C++20 之前,这仅限于用文字值初始化的对象或有限约束内的函数。C++17 允许稍微扩展用途,而 C++20 进一步扩展了它。从 C++20 开始,STL 字符串和向量类现在具有 constexpr 限定的构造函数和析构函数,允许在编译时调用它们。这也意味着必须在编译时释放为字符串或向量对象分配的内存。

安全的比较整数

典中典例子:

int x{ -3 };
unsigned y{ 7 };
if(x < y) puts("true");
else puts("false");

它会打印 false。

问题是 x 是有符号的,而 y 是无符号的。标准化行为是将有符号类型转换为无符号以进行比较。这似乎违反直觉,不是吗?事实上,将无符号值转换为相同大小的有符号值,因为有符号整数使用二进制补码表示法(使用最高有效位作为符号)。给定相同大小的整数,最大有符号值是无符号值的一半。使用此示例,如果整数是 32 位,-3(有符号)将变为 FFFF FFFD(十六进制),或 4,294,967,293(无符号十进制),不小于 7。

这下看懂,那有没有办法避免这种抽象错误呢?有:

#include <utility>
int main() {
    int x{ -3 };
    unsigned y{ 7 };
    if(cmp_less(x, y)) puts("true");
    else puts("false");
}

这个玩意好说:实际上就是模板转化一下:

template< class T, class U >
constexpr bool cmp_less( T t, U u ) noexcept
{
    using UT = make_unsigned_t<T>;
    using UU = make_unsigned_t<U>;
    if constexpr (is_signed_v<T> == is_signed_v<U>)
        return t < u;
    else if constexpr (is_signed_v<T>)
        return t < 0 ? true : UT(t) < u;
    else
        return u < 0 ? false : t < UU(u);
}

<=> :)

Spaceship运算符!哈哈,这个东西用来化简比较运算符的

三向比较的工作方式不同。它返回三种状态之一。如果操作数相等,宇宙飞船运算符将返回等于 0 的值;如果左侧操作数小于右侧操作数,则返回负值;如果左侧操作数大于右侧运算符,则返回正值。

 const int a = 7; const int b = 42; static_assert((a <=> b) < 0); 

返回的值不是整数。它是 <compare> 标头中的一个对象,与 0 进行比较。 如果操作数具有整数类型,则运算符从 <compare> 库中返回一个 strong_ordering 对象。

  • strong_ordering::equal // 操作数相等

  • strong_ordering::less // lhs 小于 rhs

  • strong_ordering::greater // lhs 大于 rhs

如果操作数具有浮点类型,则运算符返回 partial_ordering 对象:

  • partial_ordering::equivalent // 操作数相等

  • partial_ordering::less // lhs 小于 rhs

  • partial_ordering::greater // lhs 大于 rhs

  • partial_ordering::unordered // 如果操作数无序

这些对象旨在使用常规比较运算符(例如,(a <=> b) < 0)与文字零 (0) 进行比较。这使得三向比较的结果比传统比较更精确。 如果这一切看起来有点复杂,那没关系。它的真正威力在于它作为对象的统一比较运算符的应用。

当然还可以自己定义:

struct Frac {
    long n;
    long d;
    constexpr Frac(int a, int b) : n{a}, d{b} {}
    constexpr double dbl() const {
        return static_cast<double>(n) / 
          static_cast<double>(d);
    }
    constexpr auto operator<=>(const Frac& rhs) const {
        return dbl() <=> rhs.dbl();
    };
    constexpr auto operator==(const Frac& rhs) const {
        return dbl() <=> rhs.dbl() == 0;
    };
};

http://www.kler.cn/a/384683.html

相关文章:

  • Latex中给公式加边框
  • 验证二叉搜索树
  • Spring Boot——日志介绍和配置
  • 【论文复现】自动化细胞核分割与特征分析
  • 【wxWidgets GUI设计教程 - 高级布局与窗口管理】
  • 浅谈QT用法
  • IP SSL证书
  • 22.04Ubuntu---ROS2使用rclcpp编写节点
  • Catsxp云游戏白屏
  • 飞牛fnOs内网穿透-使用Lucky实现ipv6动态解析+HTTPS访问NAS服务
  • Go-性能优化、自动内存管理
  • Spring Boot详解:从入门到精通
  • File.separator与File.separatorChar的区别
  • 166页PDF | 埃森哲-XX集团企业架构数字化整体规划设计方案(限免下载)
  • Javaweb梳理10——Maven
  • 2020年美国总统大选数据分析与模型预测
  • 【人工智能】利用大语言模型(LLM)实现机器学习模型选择与实验的自动化
  • 提交linux kernel patch流程
  • 【C++】异常处理机制(对运行时错误的处理)
  • vue2 pdf 链接地址打开
  • “让工作更简单智能“ - 经纬恒润自主研发INTEWORK系列工具
  • 【信号处理】基于联合图像表示的深度学习卷积神经网络
  • HarmonyOS第一课——DevEco Studio的使用
  • 使用Spring Boot搭建简单的web服务
  • Spring Boot代理问题
  • SpringBoot(二)