2014-05-19 73 views
9

這個問題正在考慮顯式實例化模板類。如何明確instanciate基本模板類?

考慮從另一個模板類A<T>來源的模板類B<T>。我想明確instanicate B<T>,因爲它的方法是從動態鏈接調用的,所以方法必須是實例化的,儘管它們沒有在代碼本身中調用。當然,也會調用從A<T>繼承的方法,所以它們也必須立即執行。

看來,C++不實例化基地類時明確instanciating模板類,如問這樣一個問題: Do Explicit Instantiations of C++ Class Templates Instantiate Dependent Base Classes? 例子:

template<typename T> 
class A{ void foo(){...} }; 

template<typename T> 
class B : public A<T> {} 

template class B<int>; // This will NOT instanciate A<int>::foo()!!! 

當然,我還需要實例化所有的基類。但是,我不想用這個負擔代碼,因爲類層次可能非常深。考慮包含10個或更多模板類的類層次結構。不應該敦促客戶寫10個明確的模板實例。這不僅是很多寫作,當我引入對類層次結構的更改時,它也會中斷。

相反,我想達到某種方式,每當B<T>被實例化的,那麼都是它的基類。我試圖簡單地實例化B中的基類本身,如下所示:

template<typename T> 
class B : public A<T> { 
    template class A<T>; // Does not compile! 
} 

但是這不能編譯。有沒有其他方法可以實現這一目標?

回答

2

也許不是優雅,但至少可行的:提供一個宏來實例化模板,並要求用戶使用宏手動實例代替:

// in A.hpp 
#define INSTANTIATE_A(T) template class A<T>; 

// in B.hpp 
#define INSTANTIATE_B(T) \ 
    INSTANTIATE_A(T)  \ 
    template class B<T>; 

而且,如果你喜歡「污染」類接口強制使用實例化宏:添加protected成員,該成員調用模板的所有其他成員函數和基類中的版本。例如:

template<typename T> 
class A 
{ 
    void foo() {...} 
protected: 
    void instantiate() { foo(); } 
}; 

template<typename T> 
class B : public A<T> 
{ 
    void bar() {...} 
protected: 
    void instantiate() { A<T>::instantiate(); bar(); } 
}; 

template class B<int>; // Now works as expected 

更新:

替代第二溶液:取所有成員的函數指針,並將它們保存到臨時變量:

template<typename T> 
class A 
{ 
    void foo() {...} 
protected: 
    void instantiate() { void (A::*p)() = &A::foo; } 
}; 

template<typename T> 
class B : public A<T> 
{ 
    void bar() {...} 
protected: 
    void instantiate() { A<T>::instantiate(); void (B::*p)() = &B::foo; } 
}; 
+0

與第二解決方案的問題有些方法具有較大的簽名,並且生成用於提供給方法的值並不容易。第一個會工作,但確實很醜陋:(。 – gexicide

+0

增加了第二個解決方案的變體,儘管這是一個冗長而不是真正需要的:這個想法是'instantiate()'永遠不會真正執行。 –

+0

好吧,那個比較可行,但是接口很大,所以枚舉所有的方法比枚舉所有的基類要多得多,我希望還有其他方法可以解決這個問題,不過要感謝這個答案。 – gexicide