C++14新特性

C++14

语言特性

二进制字面量

二进制字面量提供了一种方便的方式来表示二进制数字。可以用’分隔数字。

0b110 // == 6
0b1111'1111 // == 255

通用 lambda 表达式

C++14 现在允许在参数列表中使用auto类型说明符,从而启用多态 lambda。

auto identity = [](auto x) { return x; };
int three = identity(3); // == 3
std::string foo = identity("foo"); // == "foo"

Lambda 捕获列表初始化

这允许创建使用任意表达式初始化的 lambda 捕获。赋予捕获值的名称不需要与封闭范围内的任何变量相关,并在 lambda 主体中引入一个新名称。在创建 lambda 时(而不是在调用它时)计算初始化表达式。

int factory(int i) { return i * 10; }
auto f = [x = factory(2)] { return x; }; // 返回 20

auto generator = [x = 0] () mutable {
  // 这不会在没有“mutalbe”的情况下编译,因为我们在每次调用时都修改 x
  return x++;
};
auto a = generator(); // == 0
auto b = generator(); // == 1
auto c = generator(); // == 2

因为现在可以将值移动(或转发)到以前只能通过复制或引用捕获的 lambda 中,所以我们现在可以按值在 lambda 中捕获仅移动类型。

请注意,在下面的示例中,=左侧的task2的捕获列表中的p是 lambda 主体私有的新变量,并且不引用原始p

auto p = std::make_unique<int>(1);

auto task1 = [=] { *p = 5; }; // 错误: std::unique_ptr无法被复制
// vs.
auto task2 = [p = std::move(p)] { *p = 5; }; // OK: p 被移动构造成闭包对象
// 创建 task2 后原始 p 为空

使用此引用捕获可以具有与引用变量不同的名称。

auto x = 1;
auto f = [&r = x, x = x * 10] {
  ++r;
  return r + x;
};
f(); // sets x to 2 and returns 12

返回类型推导

在 C++14 中使用自动返回类型,编译器将尝试为您推断类型。使用 lambdas,您现在可以使用 auto 推断其返回类型,这使得返回推断的引用或右值引用成为可能。

// 推导类型为`int`.
auto f(int i) {
 return i;
}
template <typename T>
auto& f(T& t) {
  return t;
}

// 返回推导类型的引用
auto g = [](auto& x) -> auto& { return f(x); };
int y = 123;
int& z = g(y); // `y`的引用

decltype(auto)

decltype(auto)类型说明符也像auto一样推导出一个类型。但是,它在保留引用和cv限定符的同时推断返回类型,而auto不会。

const int x = 0;
auto x1 = x; // int
decltype(auto) x2 = x; // const int
int y = 0;
int& y1 = y;
auto y2 = y1; // int
decltype(auto) y3 = y1; // int&
int&& z = 0;
auto z1 = std::move(z); // int
decltype(auto) z2 = std::move(z); // int&&
// 注意:对泛型代码特别有用

// 返回类型是 `int`.
auto f(const int& i) {
 return i;
}

// 返回类型是 `const int&`.
decltype(auto) g(const int& i) {
 return i;
}

int x = 123;
static_assert(std::is_same<const int&, decltype(f(x))>::value == 0);
static_assert(std::is_same<int, decltype(f(x))>::value == 1);
static_assert(std::is_same<const int&, decltype(g(x))>::value == 1);

放宽对 constexpr 函数的约束

在 C++11 中,constexpr函数体只能包含一组非常有限的语法,包括(但不限于):typedefusing和单个return语句。在 C++14 中,允许的语法集大大扩展,包括最常见的语法,例如if语句、多个返回、循环等。

constexpr int factorial(int n) {
  if (n <= 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}
factorial(5); // == 120

变量模板

C++14 允许对变量进行模板化:

template<class T>
constexpr T pi = T(3.1415926535897932385);
template<class T>
constexpr T e  = T(2.7182818284590452353);

[[deprecated]] 属性

C++14 引入了[[deprecated]]属性来指示不鼓励使用单元(函数、类等)并可能产生编译警告。如果提供了原因,它将包含在警告中。

[[deprecated]]
void old_method();
[[deprecated("Use new_method instead")]]
void legacy_method();

标准库

标准库类型的用户定义字面量

标准库类型的新用户定义字面量,包括chronobasic_string的新内置文字。这些可以是constexpr,这意味着它们可以在编译时使用。这些字面量的一些用途包括编译时整数解析、二进制字面量和虚数字面量。

using namespace std::chrono_literals;
auto day = 24h;
day.count(); // == 24
std::chrono::duration_cast<std::chrono::minutes>(day).count(); // == 1440

编译时整数序列

类模板std::integer_sequence表示整数的编译时序列。有一些建立在上面的助手:

  • std::make_integer_sequence<T, N> - 创建一个类型为 T 的 0, …, N - 1 序列。
  • std::index_sequence_for<T...> - 将模板参数包转换为整数序列。

将数组转换为元组:

template<typename Array, std::size_t... I>
decltype(auto) a2t_impl(const Array& a, std::integer_sequence<std::size_t, I...>) {
  return std::make_tuple(a[I]...);
}

template<typename T, std::size_t N, typename Indices = std::make_index_sequence<N>>
decltype(auto) a2t(const std::array<T, N>& a) {
  return a2t_impl(a, Indices());
}

std::make_unique

std::make_unique是创建std::unique_ptr实例的推荐方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值