C++17 新特性_第一章 C++17 语言特性___has_include,u8字符字面量

本文记录C++17新特性之__has_include和u8字面量。

文章目录

  • [第一章 C++17语言特性](#第一章 C++17语言特性)
    • [1.10 __has_include](#1.10 __has_include)
      • [1.10.1 __has_include 实现原理](#1.10.1 __has_include 实现原理)
      • [1.10.2 举例](#1.10.2 举例)
    • [1.11 u8字符字面量](#1.11 u8字符字面量)

第一章 C++17语言特性

1.10 __has_include

在C++17之前,在编写跨平台代码时,通常面临这样一个难题:如何直到当前环境包含头文件呢?以前我们只依赖构造系统(如CMake)在编译之前进行检测,如:

cpp 复制代码
#ifdef HAVE_BOOST_OPTIONAL
    #include <boost/optional.hpp>
#else  
    #include "s.h"
#endif

这种方式缺点,代码和构建脚本耦合,移植性差,如果用户只想把.hpp 扔进项目中用,还得去配置构建系统。

C++17带来了这种问题的解决办法。

1.10.1 __has_include 实现原理

__has_include 是一个预处理器表达式(Preprocessor Expression),工作原理为:

1 它接受一个头文件名称作为参数(可以是
或 "header")。
2 编译器在预处理阶段尝试在包含路径(Include Paths)中查找这个文件。
3 如果找到了,求值结果为 1(True)。
4 如果没找到,求值结果为 0(False)

1.10.2 举例

示例1:比如std::optional是C++17的,但如果用户环境只有C++14,可以降级使用boost::optional。

cpp 复制代码
#if __has_include(<optional>)
    #include <optional>
    namespace my_lib { std::optional; }

#elif __has_include(<experimental/optional>)
    // 可能是早期的 C++14/17 过渡环境
#include <experimental/optional>
    namespace my_lib { using std::experimental::optional; }

#elif __has_include(<boost/optional.hpp>)
// 只有 Boost
    #include <boost/optional.hpp>
    namespace my_lib { using boost::optional; }

#else
    // 都没有,报错或者使用简易手写版
    #error "Missing <optional> implementation"
#endif

示例2:跨平台文件系统的支持

std::filesystem 的标准化之路非常坎坷,不同编译器头文件位置不同。用 __has_include 可以完美解决:

cpp 复制代码
#if __has_include(<filesystem>)
    #include <filesystem>
    namespace fs = std::filesystem;

#elif __has_include(<experimental/filesystem>)
    #include <experimental/filesystem>
    namespace fs = std::experimental::filesystem;
#else
    #error "No filesystem support found"

#endif

示例3:检测第三方库是否存在

假设我们写了一个JSON序列化库,如果用户安装了nlohmann/json.hpp,你就提供自动转换支持,否则就不提供。

cpp 复制代码
#if __has_include(<nlohmann/json.hpp>)
    #include <nlohmann/json.hpp>
    
    // 只有在检测到头文件时,才定义这个转换函数
    void to_json(nlohmann::json& j, const MyClass& p) {
        j = nlohmann::json{{"name", p.name}, {"id", p.id}};
    }
#endif

这样,你的库就变成了"自适应"的:用户有环境就增强功能,没有就保持精简,无需修改任何构建配置。

1.11 u8字符字面量

在源码中包含非ASCII字符(比如汉字)时,源文件编码与编译器对字符集的解释不统一,导致不同平台/工具链行为不一致。

C++11 引入 u8,在 C++11/14/17 中 u8"..." 的类型是 const charN(即以 UTF‑8 编码的窄字节数组)。C++20 起元素类型改为 char8_t(即 const char8_tN)。

见C++20的char8_t.

C++20已经不支持 u8了。

相关推荐
沫璃染墨2 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
xiaoye-duck3 小时前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
旖旎夜光5 小时前
【C++ 基础入门】类和对象(上):封装、对象模型与 this 指针
开发语言·c++·笔记·学习
小超人诞生日记5 小时前
C++ 智能指针的使用及其原理详解
c++·算法
akinggw6 小时前
libagentcore - 一个基于c++的AI多agent系统升级到2.0版本
开发语言·jvm·c++
繁星蓝雨7 小时前
C++设计原理———多重继承(虚基类、菱形继承、委托、重命名、基类和成员初始化)
c++·委托·多重继承·mi·显式初始化列·虚基类·对象布局
旖旎夜光8 小时前
【C++ 基础入门】命名空间、输入输出、缺省参数与函数重载
开发语言·c++·笔记·学习
扶尔魔ocy9 小时前
【QT入门到晋级】用开源的自定义控件开发
c++·qt·自定义控件
akinggw10 小时前
libsherpacore - 基于 sherpa-onnx 的 C++ 语音交互静态库
c++·交互·语音识别
xiaoye-duck10 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt