c++11-模板元实战2
前言
黑魔法,应用场景 :
1.实现宿生语言
2.实现一些常规手段做不到的东西,比如 c++11::share_prt::enable_share_from_this
3.作为实现各种库的基本组件 :Stl,Boost,标准库都大量运用了模板元技术
很多人比较排斥这个东西...个人觉得实用就行,工具终究是为人服务的
just enjoy it 😃
推荐的资料
《C++ Templates》
《C++模板元编程》
C++11模板元入门 https://www.cnblogs.com/qicosmos/p/4480460.html
C++高质量社区 http://purecpp.org/
Part 2.1 CRTP
比较奇异的一种技术,我是从std::share_ptr::enable_share_from_this了解到的
1.通过继承基类(CRTP)来扩展派生类的接口
常规的继承时通过子类来扩展基类的功能
而CRTP反过来了...非常奇妙
实现一个可以被继承的单例模式
#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
template<typename T>
struct signle
{
public :
static T& get_signle()
{
static T ret;
return ret;
}
protected :
signle()
{}
signle(signle const& rhs) = delete;
};
struct son : signle<son>
{
friend class signle<son>;
protected :
son()
{
cout << "son" << endl;
}
};
int main()
{
auto &ret = son::get_signle();
cout << &ret << "\n";
return 0;
}
这样就没了,可以看到,能很方便的通过继承集成功能
2.实现一个调用链
这个文章的第三个例子,很清晰了
就是要求子类和父类都以父类的引用返回,实现调用链
https://zhuanlan.zhihu.com/p/137879448
3.实现静态多态
CRTP静多态的基本模式,cast是关键点,因为是安全的向下转型,static_cast就行了,没必要dynamic_cast
template<typename T>
struct crtp
{
T& cast()
{
return static_cast<T&>(*this); // safe
}
void doit()
{
cast().doit();
}
};
有两种实现方式,一种是不采用CRTP的普通模板静多态,区别见下面这个问题 + 第一个回答
https://www.zhihu.com/question/332147621
和普通静多态相比,CRTP的特点
1.可以有默认行为,普通的静态多态要求每个子类必须写函数
2.可以很好的实现-设计模式-模板方法模式-即把一些公共操作提取到基类-避开继承导致的运行时消耗
3.采用多态的地方,都可以采用CRTP的方法,利用模板自己实现虚函数...编码略微复杂...但是可以提高运行速度...也就是去除运行时处理虚表的消耗...不太安全
非以上情况的静多态,采用普通静态多态更合适
c++ 实现原型模式:clone()
等效于手工实现了虚表
#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
struct AbstractShape
{
enum class_type {Square,Circle} name;
};
template <typename Derived>
struct Shape : public AbstractShape // Shape中填写默认操作
{
Derived& cast()
{
return static_cast<Derived&>(*this);
}
void doit_face()
{
cast().doit();
}
void doit()
{
cout << "shape" << endl;
}
AbstractShape* clone_face()
{
return cast().clone();
}
AbstractShape* clone()
{
cout << "debug+ clone+ " << typeid(Derived).name() << endl;
return static_cast<AbstractShape*>(new Derived(cast()));
}
};
struct Square : public Shape<Square>
{
Square()
{
name = AbstractShape::Square;
}
void doit()
{
cout << "Square doit" << endl;
}
};
struct Circle : public Shape<Circle>
{
Circle()
{
name = AbstractShape::Circle;
}
AbstractShape* clone()
{
cout << "debug+ clone+ null" << endl;
return nullptr;
}
};
#define call_2(rhs,func_name) \
do{ \
switch(rhs -> name) \
{ \
case AbstractShape::Square : \
{ \
static_cast<Shape<Square>*>(rhs) -> func_name(); \
break; \
} \
case AbstractShape::Circle : \
{ \
static_cast<Shape<Circle>*>(rhs) -> func_name(); \
break; \
} \
} \
}while(0)
#define call_3(rhs,func_name,__result) \
do{ \
switch(rhs -> name) \
{ \
case AbstractShape::Square : \
{ \
__result = static_cast<Shape<Square>*>(rhs) -> func_name(); \
break; \
} \
case AbstractShape::Circle : \
{ \
__result = static_cast<Shape<Circle>*>(rhs) -> func_name(); \
break; \
} \
} \
}while(0)
#define VARGS_(_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,N,...) N
#define VARGS(...) VARGS_(__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)
#define CONCAT_(a,b) a##b
#define CONCAT(a,b) CONCAT_(a,b)
#define call(...) CONCAT(call_,VARGS(__VA_ARGS__))(__VA_ARGS__)
void f(AbstractShape * rhs)
{
cout << "-----------------------" << endl;
call(rhs,doit_face);
AbstractShape* p;call(rhs,clone_face,p);
if (p != NULL)
call(p,doit_face);
cout << "-----------------------" << endl << endl;
}
int main()
{
vector<AbstractShape*> v;
v.emplace_back(new Square);
v.emplace_back(new Circle);
v.emplace_back(new Square);
for (auto it : v)
f(it);
return 0;
}
本文来自博客园,作者:XDU18清欢,转载请注明原文链接:https://www.cnblogs.com/XDU-mzb/p/14860168.html