2017-05-03 14 views
1

這是一個最小的示例,假設我有一個矢量類,其大小可以靜態確定或動態確定。我允許構造函數的不同語法,如下例所示。選擇具有不同模板參數並導致編譯失敗的模板類構造函數

template<int RowAtCompileTime> 
class Vector{ 
    //Other Details 
    int rowNumber; 
public: 
    //For vectors with size known at compile time 
    Vector(){ 
     static_assert(RowAtCompileTime > 0,"Cannot do this"); 
     rowNumber = RowAtCompileTime; 
    } 
    //For vectors with dynamic size 
    Vector(const int _rowNumber){ 
     static_assert(RowAtCompileTime<=0, "Cannot do this"); 
     rowNumber=_rowNumber; 
    } 
}; 

template class Vector<0>; 
template class Vector<1>; 

int main(){ 
    //do nothing 
    return 0; 
} 

根據語法,我們的目標是如此,只有一個構造函數應該調用。假設模板參數RowAtCompileTime小於0,表示它是動態的,只有構造函數Vector(const int _rowNumber)應該可調用。

該代碼不會在std = C++ 11下的g ++ - 4.8下編譯,因爲構造函數將根據this實例化所有接口。從同一個網站上看來,不可能通過SFINAE來傳遞(但是,我對這個概念還很陌生,我不確定這是否是真的)。可以提供部分模板專業化,但如果有許多參數(如RowAtCompileTime),則該任務看起來非常令人生畏。

回答

1

這可能與SFINAE;只用函數模板的工作,所以我們需要構造函數模板:

//For vectors with size known at compile time 
template <int V = RowAtCompileTime, typename = std::enable_if_t<(V > 0)>> 
Vector() { 
    rowNumber = V; 
} 
//For vectors with dynamic size 
template <int V = RowAtCompileTime, typename = std::enable_if_t<(V <= 0)>> 
Vector(const int _rowNumber) { 
    rowNumber = _rowNumber; 
} 

然後

Vector<0> v1(10); 
Vector<1> v2; 

BTW:static_assertš變得毫無意義這個實現,他們將永遠不會被解僱。但總是隻有一個構造函數是可調用的,取決於模板參數。調用不正確的構造函數會導致編譯失敗。

LIVE

+0

非常感謝您的及時回覆。我想知道你是否會如此善意地解釋爲什麼我需要額外的模板參數'template '?非常感謝 –

+0

@RanWang由於SFINAE僅適用於函數模板,因此我們必須製作構造函數模板並引入模板參數;並且您想根據模板參數'RowAtCompileTime'選擇構造函數,所以我們引入一個新的模板參數'V',其默認值爲'RowAtCompileTime'。 – songyuanyao