[英]C++ only create an instance of a class if a condition on the template type is met
[英]How to prevent instantiation of a C++ template class method when a specific condition is met?
我正在編寫一個通用的矢量模板類(幾何實體,而不是容器),帶有以下簽名......
template< typename T, unsigned N >
class vector
{...}
...其中T是算術類型,N是維度。 我想將交叉乘積定義為運算符的重載^(位於類定義內)並僅在N == 3時啟用它。我現在擁有的是:
typename boost::lazy_enable_if_c< (N == 3), vector >::type
inline operator ^(const vector &rhs) const
{
vector ret;
ret(0) = val_[1] * rhs(2) - val_[2] * rhs(1);
ret(1) = val_[2] * rhs(0) - val_[0] * rhs(2);
ret(2) = val_[0] * rhs(1) - val_[1] * rhs(0);
return ret;
}
不幸的是,使用N!= 3實例化此模板,即使未引用operator ^,也會產生以下錯誤:
error: no type named ‘type’ in ‘struct boost::lazy_enable_if_c < false, flare::math::vector < flare::math::fixed < short int, 8u >, 2u > >’
我究竟做錯了什么? 在這種情況下是否有boost :: enable_if的替代方案?
非常感謝你。
根據文檔 ,錯誤消息的lazy_enable_if
是“ lazy_enable_if
的第二個參數必須是一個類類型,只要第一個參數(條件)為真,就定義一個名為type
的嵌套類型。” 這里顯然不滿意(除非你的vector
類型碰巧包含typedef something type;
)。
你這里不需要lazy_...
.. 根據文檔,僅在第二個arg未定義時才需要(例如,如果第二個arg是typename foo<T>::bar
,並且沒有為所有類型T
定義bar
類型)。 將始終定義vector
(這里表示vector<T, N>
)。
所以一定要嘗試擺脫lazy_
,或者創建一個do-nothing traits類template <typename T> struct nop { typedef T type; };
template <typename T> struct nop { typedef T type; };
並使用nop<vector>
將第二個arg替換為lazy_enable_if_c
。 但我的猜測是你至少已經嘗試過前者了。 :)
而現在我明白為什么那樣行不通。 根據標准14.7.1 / 1:
除非已經顯式實例化了類模板特化(14.7.2)或顯式專用(14.7.3),否則在需要完全定義的對象類型或完整性的上下文中引用特化時,將隱式實例化類模板特化。類類型會影響程序的語義。 類模板特化的隱式實例化會導致類成員函數,成員類,靜態數據成員和成員模板的聲明的隱式實例化,而不是定義或默認參數的隱式實例化。
因此,任何導致類被實例化的東西都會嘗試實例化所有方法的聲明,當N != 3
時,這些聲明將失敗。 所以看起來你需要使用一個始終存在的方法來代替函數模板。 別擔心,任何體面的編譯器仍然能夠內聯:
template< typename T, unsigned N > class vector; // Fwd decl.
template< typename T, unsigned N >
inline boost::enable_if_c< (N == 3), vector<T, N> >::type
magic(const vector<T, N>& lhs, const vector<T, N>& rhs) {
/* Do the calculation as before... */
return ret;
}
template< typename T, unsigned N >
class vector {
...
inline vector operator ^(const vector &rhs) const {
return magic(*this, rhs);
}
};
這將起作用,因為除非實際調用成員函數定義 (或者他們的地址被采用等),否則不會實例化成員函數定義 。
我相信你的問題是“位於類定義中”。 如果你通過函數而不是通過方法重載操作符,我認為你會遇到麻煩。
我認為,一旦你切換到一個功能,也可能只用普通的老式專業而不是提升魔法,但我對此不太確定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.