C++ 17如何受益于Boost库
- 一、简介
- 二、搜索算法
- 三、文件系统库:filesystem
- 四、特殊数学函数:clamp、gcd等
- 五、模板增强:and、or、not
- 六、C++ 20概览
- 七、总结
一、简介
在上一篇文章中关于介绍了几个特性:std::optional
、std::variant
、std::any
和string_view
。这篇文章将将讨论更多的元素:std::filesystem
搜索器等等!还将对C++ 20简单介绍。
众所周知,Boost库提供了大量标准库中没有的方便算法、类型和特性。许多功能被“移植”到核心C++中。例如,在C++ 11中,获得了std::regex
、线程和智能指针。
对于C++ 17,从Boost中采用了以下特性:
- 词汇类型:
std::variant
,std::any
,std::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';}elsestd::cout << "?? " << filenameStr << '\n';
}
可以看到,在上面的代码中,可以有效地处理路径对象,在目录(无论是否递归)上运行迭代,并打印关于给定目录条目的各种信息。
filesystem
库由四个主要部分组成:
- 路径对象:表示系统中路径的类型。使用各种方法提取路径部分,组合它,格式之间的转换,甚至从字符串到宽字符串。
directory_entry
:保存有关某个目录内的路径的信息,以及缓存。- 目录迭代器:两个允许扫描目录的类(即只扫描一次或递归扫描一次)。
- 加上许多支持性的非成员功能:
- 获取路径信息。
- 文件操作:复制,移动,创建,符号链接。
- 最后写时间。
- 权限。
- 空间/文件大小
......
这个库是巨大的,它对依赖文件访问的应用程序是非常有益的,毕竟有哪个应用程序不需要与文件一起工作呢?
四、特殊数学函数:clamp、gcd等
Boost库提供了许多算法和函数,甚至可以帮助进行高级数学计算。例如,有一个完整的Math Toolkit 2.9.0 - 1.70.0模块,几乎包含了数学库中的所有功能。C++ 17标准用一些额外的函数扩展了这个库。
如clamp
, gcd
和lcm
:
#include <iostream>
#include <algorithm> // clamp
#include <numeric> // for gcm, lcmint 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_laguerre
, beta
, comp_ellint_1/_2/_3
, hermite
, laguerre
, rieman_zeta
等等。
这些特殊数学函数的完整列表可以在官方网址 https://en.cppreference.com/w/cpp/numeric/special_math中找到。
五、模板增强:and、or、not
P0013文献建议将元函数and_
, or_
和not_
添加到标准库中,并引用Boost.MPL
作为长期实现这些特性的标准库之一。该文献在C++ 17中被采纳为std::conjunction
、 std::disjunction
和 std::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 - https://www.boost.org/doc/libs/1_70_0/libs/range/doc/html/index.html。
现在,虽然C++ 20中的Concept
是语言的一部分,但可以使用Boost Concept Check Library来模拟它们。该库在很大程度上基于宏,但也可以获得泛型编程的一些概要,以及通过实际Concept
实现目标。
七、总结
希望这篇博文能给你更多开始使用C++ 17的动力。最新的C++标准不仅提供了许多语言特性(如if constexpr
、结构化绑定、折叠表达式……),而且还提供了来自标准库的一组广泛的实用程序。现在可以使用多种词汇表类型:variant
、optional
、any
。使用字符串视图,甚至一个重要的组件std::filesystem
。所有这些都不需要引用一些外部库。
你最喜欢的Boost功能是什么?在评论中分享你的经验吧。