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

一、简介

在上一篇文章中关于介绍了几个特性: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 MooreBoyer 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标准用一些额外的函数扩展了这个库。

clamp, gcdlcm

#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_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中,获得RangesConcepts等,但是你知道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、结构化绑定、折叠表达式……),而且还提供了来自标准库的一组广泛的实用程序。现在可以使用多种词汇表类型:variantoptionalany。使用字符串视图,甚至一个重要的组件std::filesystem。所有这些都不需要引用一些外部库。

你最喜欢的Boost功能是什么?在评论中分享你的经验吧。

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值