簡體   English   中英

如何在滿足特定條件時阻止C ++模板類方法的實例化?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM