我正在使用C++模板實現mixins,以支持基(模板)類的一些「擴展」行爲。如何在兩個mixin模板之間實現多態行爲?
template< class Ch > Base {...};
template< class T > M1 : public T {...};
template< class T > M2 : public T {...};
// etc.
如果另一個mixin存在於繼承圖中,我需要修改一個mixin中的行爲。 (理想情況下,這將是不考慮這一個混合在第一,但我願意接受,他們必須在一個特定的順序得出的限制。)
換句話說,如果我有:
typedef Base<char> base;
typedef M2< M1<base>> foo;
typedef M2<base> bar;
當M1混入時,M2方法的行爲需要改變 - M1提供了需要用於計算M2結果的數據成員。另一方面,M2對這些數據成員做了一定的保證,如果M2沒有混入,這些數據成員是完全無效的。
那麼我的問題是如何實現這個C++ '03?
我懷疑有一種方法使用模板方法和專業化,但我的模板功能不夠強大(但)。
根據dauphic的回答,我試過了,它確實有效。完全複製M2模板的需求非常可怕,我將接下來嘗試使用SFINAE方法。
#include <iostream>
#include <UnitTest++.h>
SUITE(Mixin_specialization_tests) {
template< typename Ch > struct Base {
typedef Ch * pointer_type;
pointer_type p;
};
template< class T > struct M1 : public T {
typedef typename T::pointer_type pointer_type;
pointer_type m1p;
};
template< class T > struct M2 : public T {
typedef typename T::pointer_type pointer_type;
pointer_type m2p;
int compute() {
std::cout << "unspecialized compute()" << std::endl;
return 0;
}
};
template< >
template< class B > struct M2< M1<B> > : public M1<B> {
typedef typename M1<B>::pointer_type pointer_type;
pointer_type m2p;
int compute() {
std::cout << "specialized compute()" << std::endl;
int unused = M1<B>::m1p - m2p;
return 1;
}
};
typedef Base<char> Bch;
typedef M1<Bch> M1b;
typedef M2<Bch> M2b;
typedef M2< M1<Bch> > M2m1b;
TEST(unspecialized) {
M2b m2b;
CHECK_EQUAL(0, m2b.compute());
}
TEST(specialized) {
M2m1b m2m1b;
CHECK_EQUAL(1, m2m1b.compute());
}
}
掙扎了一下後,我設法讓SFINAE變種工作爲好。該代碼主要是除了這部分是相同的:
template< class Query > struct is_M1 {
typedef char yes, (&no)[ 2 ];
static no has_m1_member(...);
template< class T, typename T::pointer_type T::* > struct dummy {};
template< class T >
static yes has_m1_member(T*, dummy<T, &T::m1p>* = 0);
BOOST_STATIC_CONSTANT(bool, value =
(sizeof(has_m1_member((Query *)0)) == sizeof(yes))
);
};
template< class T > struct M2 : public T {
typedef typename T::pointer_type pointer_type;
pointer_type m2p;
int compute() {
return compute_impl<T>();
}
template< typename B >
typename boost::enable_if< is_M1<B>, int >::type compute_impl() {
std::cout << "sfinae: m1-compute" << std::endl;
return 1;
}
template< typename B >
typename boost::disable_if< is_M1<B>, int >::type compute_impl() {
std::cout << "sfinae: non-m1-compute" << std::endl;
return 0;
}
};
正如我在下面所提到的,enable_if <>模板不處理布爾表達式(對我來說),所以我去 與disable_if <>,這似乎去做把戲。
這些都不是特別開心,因爲這個代碼將被貢獻給一個目前沒有使用boost的項目,並且由於複製整個模板的選項是維護的噩夢。但他們都完成了這項工作。我將考慮boost解決方案的答案,只是因爲希望boost代碼將成爲標準,因此不那麼令人頭疼。
謝謝大家。
你需要縮進4個空格碼形成,不僅3. :) – Xeo 2011-04-01 21:08:38
感謝,並感謝固定它。你搖滾! – 2011-04-02 12:36:36