c++ Factor泛型编程示例
c++ Factor泛型編程示例
c++ 泛型編程 之Factor (c++ 設(shè)計(jì)新思維)
一.概述
泛化仿函數(shù)是將“請(qǐng)求(函數(shù))封裝起來(lái)”,存儲(chǔ)與對(duì)象中,該對(duì)象是具有“value語(yǔ)義”的,因此支持拷貝,賦值和作為函數(shù)參數(shù)來(lái)傳值(pass by value)。通過(guò)該對(duì)象可間接的處理封裝的請(qǐng)求,類似于boost 中的function功能。本實(shí)現(xiàn)采用的是《Modern C++ Design》中的方案。更詳盡的說(shuō),具有以下特點(diǎn):
- 可封裝任何處理請(qǐng)求,可接受函數(shù)指針,成員函數(shù)指針,仿函數(shù),甚至其它泛化仿函數(shù)。
- 具備型別安全性,不會(huì)將錯(cuò)誤的型別匹配到錯(cuò)誤的函數(shù)上。
- 一種帶有“value語(yǔ)義的對(duì)象”。
先介紹下C++中的可調(diào)用體: - C風(fēng)格的函數(shù)(C like function): void fun();
- C風(fēng)格的函數(shù)指針(C like pointto function): void (*pFun)();
- 函數(shù)引用(reference to function),其行為本質(zhì)上和const pointer to function類似。
- 仿函數(shù)(functor),類中自定義了operator () 的對(duì)象。
- Operator.*和operator->*的施行結(jié)果
- 構(gòu)造函數(shù)
在上述的任一項(xiàng),可以在右側(cè)添加一對(duì)圓括號(hào)(),在里頭放入一組合適的參數(shù)。
先來(lái)討論這樣一個(gè)問(wèn)題,既然想把函數(shù)請(qǐng)求封裝到對(duì)象中,函數(shù)的參數(shù)如何確定?這里使用typelist(這是一個(gè)型別集,包含型別列表)。這里就可以把typelist作為HTFunctor的一個(gè)模板參數(shù),包含所要封裝函數(shù)的參數(shù)型別信息。下面就先介紹下typelist實(shí)作。
二.HTTypeList
[cpp] - template <class T, class U>
- struct HTTypeList
- {
-
typedef T Head; -
typedef U Tail; - };
這是typelist的基本實(shí)作(只需兩個(gè)類型),現(xiàn)在問(wèn)題是如何把n個(gè)類型連成鏈表。看下面這個(gè)例子就明白了 - typedef HTTypeList<char, HTTypeList<int, int> >
(利用模板參數(shù)推導(dǎo),編譯器自動(dòng)產(chǎn)生,而不是運(yùn)行期哦),這樣兩個(gè)以上的參數(shù)都解決了。
現(xiàn)在問(wèn)題如何定義一個(gè)參數(shù)的typelist。方法是,第二個(gè)模板參數(shù)設(shè)為NullType(空類型),這樣每個(gè)typelist都以NullType結(jié)尾,相當(dāng)于C字符串的\0功能。看NullType的實(shí)作:
[cpp] - class HTNullType {};
接著就要生產(chǎn)typelist了(一個(gè)參數(shù),兩個(gè)參數(shù),三個(gè)參數(shù)……)。這里用到宏,暫且定義4個(gè)typelist。
[cpp] - #define TYPELIST_1(T1) UTIL::HTTypeList<T1, UTIL::HTNullType>
- #define TYPELIST_2(T1, T2) UTIL::HTTypeList<T1, TYPELIST_1(T2) >
- #define TYPELIST_3(T1, T2, T3) UTIL::HTTypeList<T1, TYPELIST_2(T2, T3) >
- #define TYPELIST_4(T1, T2, T3, T4) UTIL::HTTypeList<T1, TYPELIST_3(T2, T3, T4) >
另外要解決的問(wèn)題,函數(shù)參數(shù)該是值類型(內(nèi)部?jī)?nèi)型),還是引用類型(對(duì)于對(duì)象)。選擇合適的類型顯然能提高程序速度,肯定不想傳遞大對(duì)象參數(shù)時(shí)要額外拷貝。接下來(lái)這個(gè)東西就要登場(chǎng)了——( HTTypeTraits )
三:HTTypeTraits
可用于“編譯期根據(jù)型別作判斷”的泛型技術(shù)。大家也可參看boost中的type traits。
[cpp] - // 判斷T及U是否標(biāo)示同一個(gè)類型
- template <typename T, typename U>
- struct HTIsSameType
- {
- private:
-
template<typename> -
struct In -
{ enum { value = false }; }; -
template<> -
struct In<T> -
{ enum { value = true }; }; - public:
-
enum { value = In<U>::value }; - };
[cpp] - // 依flag選擇兩個(gè)類型中的一個(gè),true為T,false為U
- template <bool flag, typename T, typename U>
- struct HTSelect
- {
- private:
-
template<bool> -
struct In -
{ typedef T Result; }; -
template<> -
struct In<false> -
{ typedef U Result; }; - public:
-
typedef typename In<flag>::Result Result; - };
[cpp] - // 編譯期bool型
- typedef char HTYes;
- struct HTNo { char padding[8]; };
- // 型別映射為型別,用于模板函數(shù)的偏特化,C++標(biāo)準(zhǔn)模板函數(shù)不能偏特化
- template
- struct HTType2Type { typedef T Type; };
- // 判斷T是否為類
- template
- struct HTIsClass
- {
-
// U為類的話,會(huì)具現(xiàn)化此重載函數(shù),因?yàn)閰?shù)為函數(shù)指針,即指向成員的函數(shù)指針 -
template <typename U> static HTYes IsClassTest(void(U::*)(void)); -
// U為非類,會(huì)具現(xiàn)化此重載函數(shù) -
// C++標(biāo)準(zhǔn):只有當(dāng)其它所有的重載版本都不能匹配時(shí),具有任意參數(shù)列表的重載版本才會(huì)被匹配 -
template <typename U> static HTNo IsClassTest(...); -
// 對(duì)于sizeof,表達(dá)式不會(huì)被真正求值,編譯器只推導(dǎo)出表達(dá)式的返回結(jié)果的型別,因此只需函數(shù)的聲明即可 -
static const bool value = sizeof(IsClassTest<T>(0)) = sizeof(HTYes); - };
- // 判斷T是否為引用類型
- template
- struct HTIsReference
- {
-
template <typename U> static HTYes IsReference(HTType2Type<U&>); -
template <typename U> static HTNo IsReference(...); -
static const bool value= sizeof(IsReference(HTType2Type<T>())) == sizeof(HTYes); - };
- template
- class HTTypeTraits
- {
- public:
-
enum { -
isVoid = -
HTIsSameType<T, void>::value || -
HTIsSameType<T, const void>::value || -
HTIsSameType<T, volatile void>::value || -
HTIsSameType<T, const volatile void>::value -
}; -
enum { isReference = HTIsReference<T>::value }; - private:
-
template<bool IsRef> -
struct AdjReference -
{ -
template<typename U> -
struct In { typedef U const & Result; }; -
}; -
template<> -
struct AdjReference<true> -
{ -
template<typename U> -
struct In { typedef U Result; }; -
}; -
typedef typename AdjReference<isReference || isVoid>:: -
template In<T>::Result AdjType; -
// 正確的選擇函數(shù)參數(shù)的類型 -
// 對(duì)于精巧型(有構(gòu)造函數(shù)和析構(gòu)函數(shù)額外調(diào)用)采用引用傳參數(shù),對(duì)于純量型(數(shù)值型別,枚舉型別,指針,指向成員的指針)采用直接傳值 -
typedef typename HTSelect<HTIsClass<T>::value, AdjType, T>::Result ParmType; - };
四:HTFunctor
HTTypeList及HTTypeTraits提供我們強(qiáng)大的功能。這讓我們實(shí)作HTFunctor更加的方便。下面直接看代碼。
[cpp] - // Functor對(duì)象明顯是個(gè)小對(duì)象,這里采用小對(duì)象分配器
- // 使用了Command模式及IMPL模式
- template
- struct HTFunctorImplBase : public HTSmallObject<>
- {
-
typedef R ResultType; -
typedef HTEmptyType Parm1; -
typedef HTEmptyType Parm2; - };
- template <typename R, class TList, class ObjClass>
- struct HTFunctorImpl;
- // 無(wú)參數(shù)版本
- template <typename R, class ObjClass>
- struct HTFunctorImpl<R, HTNullType, ObjClass> : public HTFunctorImplBase
- {
-
typedef R ResultType; -
virtual ResultType operator()(ObjClass* pObj) = 0; -
virtual HTFunctorImpl* Clone() const = 0; -
virtual ~HTFunctorImpl() {} - };
- // 一個(gè)參數(shù)版本
- template <typename R, typename P1, class ObjClass>
- struct HTFunctorImpl<R, TYPELIST_1(P1), ObjClass> : public HTFunctorImplBase
- {
-
typedef R ResultType; -
typedef typename HTTypeTraits<P1>::ParmType Parm1; -
virtual ResultType operator()(Parm1, ObjClass* pObj) = 0; -
virtual HTFunctorImpl* Clone() const = 0; -
virtual ~HTFunctorImpl() {} - };
- // 兩個(gè)參數(shù)版本
- template <typename R, typename P1, typename P2, class ObjClass>
- struct HTFunctorImpl<R, TYPELIST_2(P1, P2), ObjClass> : public HTFunctorImplBase
- {
-
typedef R ResultType; -
typedef typename HTTypeTraits<P1>::ParmType Parm1; -
typedef typename HTTypeTraits<P2>::ParmType Parm2; -
virtual ResultType operator()(Parm1, Parm2, ObjClass* pObj) = 0; -
virtual HTFunctorImpl* Clone() const = 0; -
virtual ~HTFunctorImpl() {} - };
- // 可調(diào)用體(即封裝的處理函數(shù))為仿函數(shù)
- template <class ParentFunctor, typename Fun, class ObjClass>
- class HTFunctorHandler :
-
public HTFunctorImpl -
< -
typename ParentFunctor::ResultType, -
typename ParentFunctor::ParmList, -
ObjClass -
> - {
-
typedef typename ParentFunctor::Impl Base; - public:
-
typedef typename Base::ResultType ResultType; -
typedef typename Base::Parm1 Parm1; -
typedef typename Base::Parm1 Parm2; -
HTFunctorHandler(const Fun& fun) : m_fun(fun) {} -
HTFunctorHandler* Clone() const { return new HTFunctorHandler(*this); } -
ResultType operator()(ObjClass* pObj) -
{ return m_fun(); } -
ResultType operator()(Parm1 p1, ObjClass* pObj) -
{ return m_fun(p1); } -
ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj) -
{ return m_fun(p1, p2); } - private:
-
Fun m_fun; - };
- // 可調(diào)用體(即封裝的處理函數(shù))為類成員函數(shù),調(diào)用需傳遞對(duì)象指針
- template <class ParentFunctor, typename Fun, class ObjClass>
- class HTMemFunHandler :
-
public HTFunctorImpl -
< -
typename ParentFunctor::ResultType, -
typename ParentFunctor::ParmList, -
ObjClass -
> - {
-
typedef typename ParentFunctor::Impl Base; - public:
-
typedef typename Base::ResultType ResultType; -
typedef typename Base::Parm1 Parm1; -
typedef typename Base::Parm1 Parm2; -
HTMemFunHandler(const Fun& fun) : m_fun(fun) {} -
HTMemFunHandler* Clone() const { return new HTMemFunHandler(*this); } -
ResultType operator()(ObjClass* pObj) -
{ return (pObj->*m_fun)(); } -
ResultType operator()(Parm1 p1, ObjClass* pObj) -
{ return (pObj->*m_fun)(p1); } -
ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj) -
{ return (pObj->*m_fun)(p1, p2); } - private:
-
Fun m_fun; - };
- // HTFunctor實(shí)現(xiàn)體
- template <typename R, class TList = YKNullType, class ObjClass = YKEmptyType>
- class HTFunctor
- {
-
typedef HTFunctorImpl<R, TList, ObjClass> Impl; - public:
-
typedef R ResultType; -
typedef TList ParmList; -
typedef typename Impl::Parm1 Parm1; -
typedef typename Impl::Parm2 Parm2; -
HTFunctor() : m_spImpl() {} -
HTFunctor(const HTFunctor& rhs) : m_spImpl(rhs.m_spImpl->Clone()) {} -
explicit HTFunctor(std::auto_ptr<Impl> spImpl) : m_spImpl(spImpl) {} -
HTFunctor& operator=(const HTFunctor& rhs) -
{ -
HTFunctor copy(rhs); -
Impl* p = m_spImpl.release(); -
m_spImpl.reset(copy.m_spImpl.release()); -
copy.m_spImpl.reset(p); -
return *this; -
} -
template <typename Fun> -
HTFunctor(Fun fun) -
: m_spImpl(new -
HTSelect< -
HTIsSameType<ObjClass, HTEmptyType>::value, -
HTFunctorHandler<HTFunctor, Fun, ObjClass>, -
HTMemFunHandler<HTFunctor, Fun, ObjClass> >::Result(fun)) -
{} -
ResultType operator()(ObjClass* pObj = HT_NULL) { -
return (*m_spImpl)(pObj); -
} -
ResultType operator()(Parm1 p1, ObjClass* pObj = HT_NULL) { -
return (*m_spImpl)(p1, pObj); -
} -
ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj = HT_NULL) { -
return (*m_spImpl)(p1, p2, pObj); -
} - private:
-
std::auto_ptr<Impl> m_spImpl; - };
五.Krypton Factor C++
#include
#include
#include
#include
using namespace std;
int cnt;
int n,L;
int ans;
int S[100001];
int dfs(int cur)
{
if(cnt++n){
for(int i=0;i<cur;i++){if(i%40&&i&&i<cur&&i%64!=0)cout<<" “;if(i&&i%64==0&&i<cur)cout<<endl;printf(”%c",‘A’+S[i]);ans++;}
printf("\n");
return 0;
}
for(int i=0;i<L;i++)
{
S[cur]=i;
int ok=1;
for(int j=1;j*2<=cur+1;j++)
{
int equal_=1;
for(int k=0;k<j;k++)
if(S[cur-k]!=S[cur-k-j]){equal_=0;break;}
if(equal_){ok=0;break;}
}
if(ok)if(!dfs(cur+1))return 0;
}
return 1;
}
int main()
{
while(cin>>n>>L&&n&&L){
ans=0;
cnt=0;
dfs(0);
cout<<ans<<endl;
}
return 0;
}
六.C++泛型編程與設(shè)計(jì)模式( 函數(shù)內(nèi)部類 )
class Interface {
virtual void func() =0;
};
template<class T, class P>
Interface *makeAdapter(T tt, P pp) {
int a = 10;
static int count = 10;
class Local : public Interface {
public:
Local(const T &t, const P &p) : p§, t(t) {
// cout << a << endl;
cout << count << endl;
}
virtual void func() {
}
private:
P p;
T t;
static int k;
};
return new Local(tt,pp);
};
這個(gè)例子很簡(jiǎn)單,開(kāi)始定義了一個(gè)接口,然后定義了一個(gè)方法,該方法返回一個(gè)Interface的指針,在makeAdapter方法中,定義了Local類,然后繼承自接口Interface,因?yàn)檫@里的Local是個(gè)類,是個(gè)局部的,所以無(wú)法被外部代碼所使用,這就說(shuō)明了,局部類的使用限制性還是挺大的:
- 要么就在方法內(nèi)部使用。
- 如果要在外部使用,不論是直接返回,還是存在其它的包裹方式,都必須繼承已經(jīng)存在的接口或者是基類。
局部類這種獨(dú)特的特性,非常類似于其他語(yǔ)言中的final類,如說(shuō)PHP,JAVA,因?yàn)樗蔷植康?#xff0c;所以無(wú)法被外部繼承。如果不希望類被繼承的話,局部類是個(gè)不錯(cuò)的方法。
參考鏈接:
https://blog.csdn.net/zhuyingqingfen/article/details/10124527
https://blog.csdn.net/Zero_979/article/details/81205702
https://blog.csdn.net/oKanJianLiao/article/details/80711167
總結(jié)
以上是生活随笔為你收集整理的c++ Factor泛型编程示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 自研GPU之火(续)
- 下一篇: Linux输入输出I/O