2013-03-18 32 views
6

Şablon bağımsız değişkenine bağlı olarak bir yöntemi derlemek veya engellemek için bir yol var mı? 2, 3 veya daha fazla boyutu işleyebilen bir Koordinat sınıfı oluşturmaya çalışıyorum. Ben x(), y() ve z() olarak acces yöntemleri sağlamak istiyoruz, ama ben, ben için z() kullanımını önlemek için bir static_assert kullanmak boyut (Aşağıda da görebileceğiniz gibi) Şimdilik 3. daha büyük olması halinde erişilebilir olmasını z() yöntemi istiyorum BuDerleme zamanı bağımsız değişkenine bağlı olarak kullanılabilir bir yöntem oluşturma

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

static_assert kullanılmadan derlemek kalmaması boyutun 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]; 
    } 
}; 

koordinatları ne yapmak istiyorsunuz, boyutun 2 için z() ait gizlemek varlığıdır. std :: enable_if etrafında pek çok soru gördüm, ama anladığım kadarıyla belirli aşırı yüklenmeleri etkinleştirmek veya devre dışı bırakmak için kullanmak.

Soru şudur: Bir derleme zamanı bağımsız değişkenine bağlı olarak bir yöntem hazırlamanın veya yapmanın bir yolu var mı?

+0

gibi std::enable_if kullanın: Ben c bu etiketlemelisiniz ++ veya C++ 11? – undu

+1

Olası kopya: http://stackoverflow.com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function?lq=1 – Synxis

cevap

8

Örneğin, şablon olarak işlev ilan edebilir ve bir kenara bu

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

Çalışmayan bir cevabın varyasyonunu denedim, ama seninki iyi görünüyor. – undu

6

Bunun için uzmanlık kullanabilirsiniz:

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]; 
    } 
}; 

Sen kod tekrarını önlemek için ayrı bir yapı içine dışarı paylaşılan üyeleri kaldırabilir.

+0

Paylaşılan üyeler bir temel sınıfta olabilir, sonra 'Koord' bu temel sınıftan devralın. – JSQuareD

+1

std :: enable_if'in neden geçerli olmadığı konusunda kafam karıştığımı itiraf etmeliyim, clang bunu kabul eder ve beklediğim gibi davranır. – hmjd

+0

@hmjd bu cevabı açıklıyor gibi görünüyor: http://stackoverflow.com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function?lq=1 (GCC'nin burada olduğunu tahmin ediyorum ama yanlış olabilir!) – Pubby

3

Sen uzmanlaşma uzmanlaşmaya dayalı bu yaklaşımı kullanabilirsiniz:

#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! 
} 
İlgili konular