C++拾遗
2020-04-20 本文已影响0人
龙遁流
可变参数模板函数
template <typename ...T>
void f(T... args)
{
cout << sizeof...(args) <<endl;
}
省略号的作用
- 声明一个参数包,可包含0到任意个模板参数
- 在模板定义的右边,可将参数包展开成各个独立的参数
参数包展开
- 递归函数方式展开参数包
-
参数包展开函数
template <typename T, typename ...Args> void print(T head, Args... rest) { f(head); print(rest...); }
-
递归终止函数
当参数包展开到最后一个参数时递归为止
template <typename T, typename E> void print(T t, E e) { } 或 void print() { }
-
其他示例
template <std::size_t I = 0, typename Tuple> typename std::enable_if <I == std::tuple_size<Tuple>::value>::type print(Tuple t) { } template <std::size_t I = 0, typename Tuple> typename std::enable_if <I < std::tuple_size<Tuple>::value>::type print(Tuple t) { std::count <<std::get<I>(t) <<std::endl; print<I + 1>(t); } template <typename ...Args> void printtp(Args... args) { print(std::make_tuple(args...)); }
-
- 逗号表达式和初始化列表方式展开参数包
template <typename T> void print(T t){} template <typename ...Args> void expand(Args... args) { int arr[] = { (print(args), 0)... }; std::initializer_list<int> { (print(arg), 0)... }; std::initializer_list<int> { ([&]{}(), 0)... }; }
可变参数模板类
template<class ...Args>
class tuple;
模板递归和特化方式展开参数包
//类声明
template <typename ...Args>
struct Sum;
//递归展开
template <typename First, typename ...Rest>
struct Sum<First, Rest...>
{
enum
{
value = Sum<First>::value + Sum<Rest...>::value
};
}
//递归终止
template <typename Last>
struct Sum<Last>
{
enum
{
value = sizeof(Last)
};
}
使用 std::integral_constant
消除枚举定义value
,上例可修改为
template <typename ...Args>
struct Sum;
template <typename First, typename ...Rest>
struct Sum<First, Rest...> :
std::integral_constant<int, Sum<First>::value + Sum<Rest...>::value>
{
}
template <typename Last>
struct Sum<Last> :
std::integral_constant<int, sizeof(Last)>
{
}
Sum<int, double, short>::value;
继承方式展开参数包
内存对齐的缓冲区
template <std::size_t Len, std::size_t Align = /*default-alignment*/>
struct aligned_storage;
-
Len
存储类型的大小,sizeof(T)
-
Align
该类型内存对齐的大小,alignof(T)
或者std::alignment_of<T>::value
使用
struct A
{
int avg;
}
using Aligned_A = std::aligned_storage<sizeof(A), std::alignment_of<A>::value>::type;
int main()
{
Aligned_A a, b;
new (&a) A();
b = a;
cout << reinterpret_cast<A&>(b).avg<<endl;
return 0;
}
可变模板参数和type_taits
综合应用
optional
- 惰性求值
-
std::result_of
函数返回值类型推断 -
dll
帮助类 -
lambda
链式调用
template <typename T>
class Task;
template<typename R, typename ...Args>
class Task<R(Args...)>
{
public:
Task(std::function<R(Args...)> &&f) : m_fn(std::move(f)){}
Task(std::function<R(Args...)> &f) : m_fn(f){}
R Run(Args&&... args)
{
return m_fn(std::forward<Args>(args)...);
}
template<typename F>
auto Then(F &&f) -> Task<typename std::result_of<F(R)>::type(Args...)>
{
using return_type = typename std::result_of<F(R)>::type;
auto func = std::move(m_fn);
return Task<return_type(Args...)>([func, &f] (Args&&... args)
{
return f(func(std::forward<Args>(args)...));
};
}
private:
std::function<R(Args...)> m_fn;
}
{
Task<int(int)> task([](int i){return i});
auto result = task.Then([](int i){return i + 1})
.Then([](int i){return i + 2})
.Then([](int i){return i + 3})
.Run(1);
}
- any类的实现 (只能容纳一个元素,可擦出类型,可赋给它任何类型的值)
function_traits
-
variant
类似于union
-
ScopeGuard
(确保资源对非正常返回时可以正确释放,RAII) tuple_helper
-
shared_ptr
使用默认删除器销毁数组
std::default_delete<T[]>
- 不要使用原始指针初始化多个
shared_ptr
- 不要在函数实参中创建
shared_ptr
,由于函数调用约定可能造成资源泄露 - 正确返回
this
的shared_ptr
class A : public std::enable_shared_from_this<A> { std::shared_ptr<A> GetSelf() { return shared_from_this(); } }
- 避免循环引用
析构的时候,A和B都要依赖对方先析构后才析构自己,这样循环依赖就都不会析构。使用{ shared_ptr<A> ap(new A); shared_ptr<B> bp(new B); ap->bptr = bp; bp->aptr = ap; }
weak_ptr
可解决。 -
unique_ptr
不允许复制,但可以通过move
语义移动;但可以通过函数返回给其他unique_ptr
-
unique_ptr
允许指向数组,而shared_ptr
不可以shared_ptr<int> p(new int[10], default_delete<int[]>()); unique_ptr<int[]> ptr(new int[10]); //指定删除器 unique_ptr<int, void(*)(int*)> ptr(new int(1), [](int *p){delete p;}); unique_ptr<int, function<void(int*)>> ptr(new int(1), [&](int *p){delete p;}); unique_ptr<int, MyDelete> ptr(new int(1));
-
lambda
在没有捕获变量的情况下是可以直接转换为函数指针的 -
weak_ptr
是用来监视shared_ptr
的生命周期的,不会使引用计数加1。监视shared_ptr
的资源是否存在,可用来返回this
指针和解决循环引用。-
use_count()
获取其观测的引用计数 -
expired()
观测的资源是否已被释放 -
lock()
获取观测的shared_ptr
对象
-