在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 表达式中使用 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; }
#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++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); }
支持使用 0b 开头的一串数字作为二进制表示的整型:
int a = 0b10101001110; // 1358
支持在数字中使用单引号进行分割(便于阅读)。在编译时,这些单引号会被忽略。
int a = 123'456'789; // 123456789
在C++14中,我们可以使用 auto 作为函数返回值并且不需要指明其返回类型的推导表达式
int x = 1; auto f() { return x; } /* c++11 auto f() -> decltype(x) { return x; } */
这种类型推导有一些限制:
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; }
该类用于字符串转义的处理。使用 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); }