2013-03-18 30 views
6

根據模板參數,是否有編譯方法的方法? 我正在嘗試創建一個可以處理2,3或更多維度的座標類。我想提供訪問方法爲x(),y()z(),但我想z()只有在維度大於3時纔可訪問。現在(如下所示),我使用static_assert來防止將z()用於尺寸2.根據編譯時參數提供方法

template<typename DataType, int Dimension> 
class Coord 
{ 
private: 
    std::array<DataType, Dimension> _data; 

public: 

    // how to achieve some kind of compile_if() 
    DataType& z() 
    { 
     static_assert(Dimension >= 3, "Trying to access an undefined dimension."); 
     return _data[2]; 
    } 
}; 

的座標,我想這樣做是z()隱藏存在了2維,使這一

Coord<int, 2> ci2(0,0); 
ci2.z() = 3; // shouldn't compile 

並不無需使用static_assert的編譯。 我見過很多關於std :: enable_if的問題,但是我知道它是用來啓用或禁用特定的重載。

問題是:有沒有一種方法來使一個方法可用或不依賴於編譯時參數?

+0

題外話:我應該標記這個爲C++或C++ 11? – undu 2013-03-18 16:13:54

+1

可能的重複:http://stackoverflow.com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function?lq=1 – Synxis 2013-03-18 16:16:44

回答

8

例如,你可以聲明你的函數爲模板,使用std::enable_if這樣

template<typename DataType, int Dimension> 
class Coord 
{ 
private: 
    std::array<DataType, Dimension> _data; 

public: 
    template <class T = DataType> 
    typename std::enable_if<Dimension >= 3, T&>::type 
    z() 
    { 
     return _data[2]; 
    } 
}; 
+0

我試過你的答案的一個變體,但沒有奏效,但你的答案似乎沒問題。 – undu 2013-03-18 16:41:26

6

您可以使用專門爲這樣的:

template<typename DataType, int Dimension, bool HaveZ = (Dimension >= 3)> 
class Coord; 

template<typename DataType, int Dimension> 
class Coord<DataType, Dimension, false> 
{ 
private: 
    std::array<DataType, Dimension> _data; 

public: 
}; 

template<typename DataType, int Dimension> 
class Coord<DataType, Dimension, true> 
{ 
private: 
    std::array<DataType, Dimension> _data; 

public: 

    DataType& z() 
    { 
     return _data[2]; 
    } 
}; 

可以解除共享成員到一個單獨的結構,防止重複代碼。

+0

共享成員可能在一個基類,然後'Coord'應該從這個基類繼承。 – JSQuareD 2013-03-18 16:34:29

+1

我必須承認我很困惑,爲什麼'std :: enable_if'不適用於此,clang也接受它,並按我的預期行事。 – hmjd 2013-03-18 16:40:16

+0

@hmjd這個答案似乎解釋它:http://stackoverflow.com/questions/6972368/stdenable-if-to-conditional-compile-a-member-function?lq=1(我猜GCC在這裏是正確的,但我可能是錯的!) – Pubby 2013-03-18 16:42:17

3

你可以使用基於專業化分工這一做法:

#include <array> 

template<typename DataType, int Dimension, bool = (Dimension < 3)> 
class Coord 
{ 
protected: 
    std::array<DataType, Dimension> _data; 
}; 

template<typename DataType, int Dimension> 
class Coord<DataType, Dimension, false> : public Coord<DataType, Dimension, true> 
{ 
public: 
    DataType& z() 
    { 
     return this->_data[2]; 
    } 
}; 

int main() 
{ 
    Coord<double, 3> c3; 
    c3.z(); // OK 

    Coord<double, 2> c2; 
    c2.z(); // ERROR! 
} 
相關問題