C++标准 — C++14特性

C++标准 — C++14特性

一、变量模板

在C++11及之前,我们只有针对类和函数的模板。C++14中,新增了变量模板:

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

template<class T>
T circular_area(T r)
{
	return pi<T> *r * r;
}

变量模板同样可以在类变量中使用:

template<class T>
class X {
	static T s;
};
template<class T>
T X<T>::s = 0; 

类似函数和类模板,当变量模板被引用时,则会发生实例化。

二、lambda 表达式的新增功能

1、泛化

支持在 lambda 表达式中使用 auto 定义变量类型:

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
	auto glambda = [](auto& a) { cout << a << " "; };
	int a[] = { 4, 2, 6, 3, 7, 5 };
	for_each(a, a + sizeof(a) / sizeof(int), glambda);
	cout << endl;
}

2、对捕获的变量和引用进行初始化

#include <iostream>
using namespace std;

int main()
{
	int x = 4;
	auto y = [&r = x, x = x + 1]()->int
	{
		r += 2;
		return x * x;
	}(); 
	cout << "x = " << x << " y = " << y << endl;
}

C++标准 — C++14特性

三、constexpr 函数可以包含多个语句

在C++11中,如果想使用 constexpr 方法,只能包含一个返回语句。C++14中,放宽了此要求,允许 constexpr 函数中声明变量,使用循环和条件语句等:

#include <iostream>
#include <cmath>
using namespace std;

constexpr bool isPrimitive(int number)
{
	if (number <= 0)
	{
		return false;
	}

	for (int i = 2; i <= sqrt(number) + 1; ++i)
	{
		if (number % i == 0)
		{
			return false;
		}
	}

	return true;
}

int main()
{
	cout << boolalpha << isPrimitive(102) << " " << isPrimitive(103);
	return 0;
}

在C++11中,我们一般需要通过递归来实现相同的功能:

constexpr bool isPrimitive(int number, int currentFactor, int maxFactor)
{
	return currentFactor == maxFactor ? true : 
			(number % currentFactor == 0 ? false : 
				isPrimitive(number, currentFactor + 1, maxFactor));
}

constexpr bool isPrimitive(int number)
{
	return number <= 0 ? false : isPrimitive(number, 2, sqrt(number) + 1);
}

四、整型字面量

1、二进制字面量

支持使用 0b 开头的一串数字作为二进制表示的整型:

int a = 0b10101001110; // 1358

2、数字分割符

支持在数字中使用单引号进行分割(便于阅读)。在编译时,这些单引号会被忽略。

int a = 123'456'789; // 123456789

五、返回类型自动推导

在C++14中,我们可以使用 auto 作为函数返回值并且不需要指明其返回类型的推导表达式

int x = 1;
auto f() { return x; }
/* c++11
auto f() -> decltype(x) { return x; } 
*/

这种类型推导有一些限制:

  • 一个函数中所有返回字句必须推导出相同的类型;
  • 使用 {} 包裹的数据作为返回值时,无法推导其类型;
  • 虚函数和 coroutine 不能被推导;
  • 函数模板中可以使用类型推导,但是其显式实例化和特化版本必须使用相同的返回类型描述符。

六、exchange

exchange 用于移动语义,可以使用指定的新值替换掉原值,并返回原值。其定义在C++20中被简单修改如下:

template<class T, class U = T>
constexpr // since C++20
T exchange(T& obj, U&& new_value)
{
    T old_value = std::move(obj);
    obj = std::forward<U>(new_value);
    return old_value;
}

其使用如下:

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int main()
{
	vector<int> v = {5, 6, 7};

	std::exchange(v, { 1,2,3,4 });

	std::copy(begin(v), end(v), ostream_iterator<int>(cout, " "));
	cout << endl;
}

C++标准 — C++14特性

七、quoted

该类用于字符串转义的处理。使用 out << quoted(s, delim, escape) 的形式,可以将字符串 s 的转义格式写入输出流中;使用 in >> quoted(s, delim, escape) 可以将输入流去除转义格式后写入字符串 s 中。其中,delim 指明了需要转义的字符,escape 指明了修饰该转移字符的字符:

#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;

int main()
{
	stringstream ss;
	string in = "String with spaces, and embedded \"quotes\" too";
	string out;

	auto show = [&](const auto& what) 
	{
		&what == &in
			? cout << "read in     [" << in << "]\n"
			<< "stored as   [" << ss.str() << "]\n"
			: cout << "written out [" << out << "]\n\n";
	};

	ss << quoted(in); 
	show(in);
	ss >> quoted(out);
	show(out);

	ss.str(""); 

	in = "String with spaces, and embedded $quotes$ too";
	const char delim{ '$' };
	const char escape{ '%' };

	ss << quoted(in, delim, escape);
	show(in);
	ss >> quoted(out, delim, escape);
	show(out);
}

C++标准 — C++14特性

上一篇:1074 Reversing Linked List (25 分)【难度: 一般 / 知识点: 链表】


下一篇:HTML css——常规流