问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

掌握C++17的“武器“:Boost库带来的新特性

创作时间:
作者:
@小白创作中心

掌握C++17的“武器“:Boost库带来的新特性

引用
CSDN
1.
https://blog.csdn.net/Long_xu/article/details/138037523

C++17引入了许多新特性,其中许多都是从Boost库移植过来的。本文将详细介绍这些特性,包括搜索算法、文件系统库、特殊数学函数、模板增强等,并简要介绍C++20的一些特性。

一、简介

在上一篇文章中,我们介绍了几个特性:std::optionalstd::variantstd::anystring_view。本文将继续讨论更多的元素:std::filesystem、搜索器等等!还将对C++20进行简单介绍。

众所周知,Boost库提供了大量标准库中没有的方便算法、类型和特性。许多功能被“移植”到核心C++中。例如,在C++11中,获得了std::regex、线程和智能指针。

对于C++17,从Boost中采用了以下特性:

  • 词汇类型:std::variantstd::anystd::optional
  • string_view
  • 搜索算法:Boyer Moore和Boyer Moore Horspool。
  • std::filesystem
  • 特殊数学函数。
  • template的改进。

二、搜索算法

Boost提供了三种模式搜索算法:

  • Knuth-Morris-Pratt算法,
  • Boyer-Moore算法,
  • Boyer-Moore- horspool算法。

通过使用预处理步骤,所有的算法都击败了大字符串的普通模式搜索。它们根据输入模式构建额外的表,这样搜索就更有效了。

最后两个算法被移植到C++17中,它们可以作为std::search函数的附加搜索对象使用。现在,C++17为std::search提供了一个新的重载:

template<class ForwardIterator, class Searcher>
ForwardIterator search( ForwardIterator first, ForwardIterator last,
                        const Searcher& searcher );

Searcher是一个模板参数(所以也可以自己实现),标准库提供了三种类型:

  • default_searcher
  • boyer_moore_searcher
  • boyer_moore_horspool_searcher

使用方式:

std::string testString = "Hello Super World";
std::string needle = "Super";
auto it = search(testString.begin(), testString.end(),
                    boyer_moore_searcher(needle.begin(), needle.end()));
if (it == testString.end())
    cout << "The string " << needle << " not found\n";

为每个模式创建一次搜索器对象。如果希望在不同的容器中搜索相同的文本,那么可以节省一些预处理时间。

在一些性能实验中,对于更大的模式和boyer_moore,可以获得比默认搜索器更好的性能。例如,当扫描包含547412个字符的文本内部并查找200个字母的模式时,获得了比默认搜索器快8倍的性能加速。甚至比优化后的std::string::find性能提高了3倍。

三、文件系统库:filesystem

这是对C++17和标准库的一个巨大的补充。委员会在boost::filesystem方面积累了多年的经验,对其进行了改进,提出了一个技术规范,后来合并到标准中。

典型例子:Boost中的目录迭代。

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
fs::path inputPath = GetInputPath();
for (const auto& entry : fs::directory_iterator(inputPath))
    std::cout << entry.path() << '\n';

现在,C++17的版本也有了:

#include <filesystem>
namespace fs = std::filesystem;
fs::path inputPath = GetInputPath();
for (const auto& entry : fs::directory_iterator(inputPath)) {
    std::cout << entry.path() << '\n';

觉得有什么不同吗?代码几乎与Boost一样!甚至可以稍微扩展一下,添加更多的日志输出:

#include <filesystem>
namespace fs = std::filesystem;
for (const auto& entry : fs::directory_iterator(inputPath)) {
    const auto filenameStr = entry.path().filename().string();
    if (entry.is_directory()) {
        std::cout << "dir:  " << filenameStr << '\n';
    }
    else if (entry.is_regular_file()) {
        std::cout << "file: " << filenameStr << '\n';
    }
    else
        std::cout << "??    " << filenameStr << '\n';
}

可以看到,在上面的代码中,可以有效地处理路径对象,在目录(无论是否递归)上运行迭代,并打印关于给定目录条目的各种信息。

filesystem库由四个主要部分组成:

  • 路径对象:表示系统中路径的类型。使用各种方法提取路径部分,组合它,格式之间的转换,甚至从字符串到宽字符串。
  • directory_entry:保存有关某个目录内的路径的信息,以及缓存。
  • 目录迭代器:两个允许扫描目录的类(即只扫描一次或递归扫描一次)。
  • 加上许多支持性的非成员功能:
  • 获取路径信息。
  • 文件操作:复制,移动,创建,符号链接。
  • 最后写时间。
  • 权限。
  • 空间/文件大小
  • ...

这个库是巨大的,它对依赖文件访问的应用程序是非常有益的,毕竟有哪个应用程序不需要与文件一起工作呢?

四、特殊数学函数:clamp、gcd等

Boost库提供了许多算法和函数,甚至可以帮助进行高级数学计算。例如,有一个完整的Math Toolkit 2.9.0 - 1.70.0模块,几乎包含了数学库中的所有功能。C++17标准用一些额外的函数扩展了这个库。

clampgcdlcm

#include <iostream>
#include <algorithm>  // clamp
#include <numeric>    // for gcm, lcm
int main() {
    std::cout << std::clamp(300, 0, 255) << ', ';   
    std::cout << std::clamp(-10, 0, 255) << '\n'; 
    std::cout << std::gcd(24, 60) << ', ';
    std::cout << std::lcm(15, 50) << '\n';    
}

还有一组特殊的数学函数:assoc_laguerrebetacomp_ellint_1/_2/_3hermitelaguerrerieman_zeta等等。

这些特殊数学函数的完整列表可以在官方网址 cppreference 中找到。

五、模板增强:and、or、not

P0013文献建议将元函数and_or_not_添加到标准库中,并引用Boost.MPL作为长期实现这些特性的标准库之一。该文献在C++17中被采纳为std::conjunctionstd::disjunctionstd::negation

示例:

template<typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<int, Ts>...> >
PrintIntegers(Ts ... args) { 
    (std::cout << ... << args) << '\n';
}

上面的函数PrintIntegers使用可变数量的参数,但它们都必须是int类型。

六、C++20概览

在C++20中,获得Ranges和Concepts等,但是你知道Boost中也有一个更早的版本吗?这是一个Boost中的Ranges库链接:Boost Range 2.0 - Boost Range

现在,虽然C++20中的Concept是语言的一部分,但可以使用Boost Concept Check Library来模拟它们。该库在很大程度上基于宏,但也可以获得泛型编程的一些概要,以及通过实际Concept实现目标。

七、总结

希望这篇博文能给你更多开始使用C++17的动力。最新的C++标准不仅提供了许多语言特性(如if constexpr、结构化绑定、折叠表达式……),而且还提供了来自标准库的一组广泛的实用程序。现在可以使用多种词汇表类型:variantoptionalany。使用字符串视图,甚至一个重要的组件std::filesystem。所有这些都不需要引用一些外部库。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号