跳转至

8

C++17 简介*

主要入选特性*

非类型模板参数的 auto*

模板参数分为两种,一种是类型模板参数,也是用得最多的一种:

template <typename T, typename U>
auto add(T t, U u) {
    return t+u;
} 

以上的 TU 都是类型模板参数。另一种是非类型模板参数,它可以让不同的字面量成为模板的参数:

template <typename T, int BufSize>
class buffer_t {
public:
    T& alloc();
    void free(T& item);
private:
    T data[BufSize];
}

buffer_t<int, 100> buf; // 100 作为模板参数

以前我们必须明确非类型模板参数的具体类型,C++17 允许使用 auto 关键字,从而让编译器推导具体的类型:

template <auto value> void foo() {
    return;
}

foo<10>();  // value 被推导为 int 类型

std::variant*

std::vairant<> 可以用于存储和操作不同类型的对象。在前面迭代 std::tuple 时,使用了 boost::variant<>。提供给 variant<> 的类型模板参数可以让一个 variant<> 容纳提供的几种类型的变量。

C++17 加入了 std::variant<>,我们可以用一下的代码实现元组遍历:

#include <variant>
template <size_t n, typename... Args>
std::variant<Args...> _tuple_index(size_t i, const std::tuple<Args...>& tpl) {
    if (i == n)
        return std::get<n>(tpl);
    else if (n == sizeof...(Args) - 1)
        throw std::out_of_range("越界.");
    else
        return _tuple_index<(n < sizeof...(Args)-1 ? n+1 : 0)>(i, tpl);
}
template <typename... Args>
std::variant<Args...> tuple_index(size_t i, const std::tuple<Args...>& tpl) {
    return _tuple_index<0>(i, tpl);
}

结构化绑定 Structured bindings*

结构化绑定提供了类似其它语言中提供的多返回值的功能。我们可以通过 std::tuple 来构造一个元组,囊括多个返回值。但我们没有一种简单的方法直接从元组中拿到并定义元组中的元素,尽管可以通过 std::tie 拆包,但我们依然必须清楚元组包含多少对象,都是什么类型。

C++17 给出的结构化绑定允许:

std::tuple<int,double,std::string> f() {
    return std::make_tuple(1,2.3,"456");
}
auto [x,y,z] = f(); // x,y,z 分别被推导为int,double,std::string

变量声明的强化*

变量的声明虽然能够在任何位置,但是在没办法在 ifswitch 语句中声明一个临时变量。C++17 消除了这一限制,我们可以:

if (auto p = m.try_emplace(key, value); !p.second) {   
    //...
} else {
    //...
}

最后更新: November 26, 2020