本文用于随手记录一些自己学习中碰到的C++特性。
1.结构化绑定
对于以下std::tuple
std::tuple<int, std::string, double> foo{ 1, "foo", 3.14 };
在未有该特性前,对其解包很麻烦,使用std;:get要写一大串
std::cout << std::get<0>(foo) << std::get<1>(foo) << std::get<2>(foo);//print 1 foo 3.14
或者定义一堆变量再调用std::tie方法
int a;
std::string b;
double c;
std::tie(a, b, c) = foo;
std::cout << a << b << c;//print 1 foo 3.14
现在只需要使用结构化绑定,十分优雅
auto&& [a, b, c] = foo;
std::cout << a << b << c;//print 1 foo 3.14
2.用户定义字面量
在chrono库中有个用于sleep的函数,它长这样
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
上面的那个1s是个啥?打开chrono库找到了这个1s的实现
_NODISCARD constexpr chrono::seconds operator"" s(unsigned long long _Val) { // return integral seconds
return chrono::seconds(_Val);
}
重点就在这个 operator"" s 上,其实这用到了用户定义字面量的特性,这使得用户可以自定义后缀。可以使用该特性来定义一个二进制数后缀,实现如下
using LL = long long;
LL operator""B(const char* num, size_t length) {
std::function<LL(const char*, size_t&&, const size_t&, LL&&)> decimal_2_binary;
decimal_2_binary = [&](const char* num, size_t&& now, const size_t& length, LL&& ans) {
if (now == length) return (ans << 1) | (num[now] - '0');
return decimal_2_binary(num, now + 1, length, (ans << 1) | (num[now] - '0'));
};
return decimal_2_binary(num, 0, length - 1, 0);
}
然后我们就能这样定义二进制数
auto&& a = "110"B;
auto&& b = "111101"B;
std::cout << a << b;//print 6 61
3.折叠表达式
使用可变参数模板,在C++17之前展开比较繁琐。例如,实现一个不定参数的求和函数可能需要这么写
template<typename T>
T sum(T&& arg) {
return arg;
}
template<typename T, typename ...args>
auto sum(T&& a, args&&... rest) {
return a + sum(rest...);
}
std::cout << sum(1, 2, 3, 4, 5);//print 15
在C++17有了折叠表达式之后,配合C++14的泛型lambda使用,可以简化成这样
auto&& sum = [](auto&&... args){
return (... + args);
};
std::cout << sum(1, 2, 3, 4, 5);//print 15