2013-03-18 24 views
6

Czy istnieje sposób kompilacji metody, czy nie, w zależności od argumentu szablonu? Próbuję utworzyć klasę współrzędnych, która może obsłużyć 2, 3 lub więcej wymiarów. Chcę zapewnić metody Acces jak x(), y() i z(), ale chciałbym z() sposób, aby były dostępne tylko wtedy, gdy wymiar jest większy niż 3. Na razie (jak widać poniżej), używam static_assert celu zapobieżenia wykorzystywania z() dla współrzędne wymiaru 2.Udostępnienie metody w zależności od argumentu o kompilacji

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

Co chciałbym zrobić to ukryć istnienie z() dla wymiaru 2, tak, że ten

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

nie kompiluje bez użycia static_assert. Widziałem wiele pytań dotyczących std :: enable_if, ale z tego co rozumiem, należy włączyć lub wyłączyć określone przeciążenia.

Pytanie brzmi: czy istnieje sposób na udostępnienie metody w zależności od argumentu kompilacji?

+0

bok: mam oznaczyć to jako C++ lub C++ 11? – undu

+1

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

Odpowiedz

8

Na przykład, można zadeklarować swoją funkcję jako szablon i używać std::enable_if jak ten

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

Próbowałem wariacji twojej odpowiedzi, która nie działała, ale twoja wydaje się w porządku. – undu

6

Można użyć do tego specjalizacji:

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

Można podnieść udostępnione członkom się w oddzielnej struktury w celu zapobieżenia powielania kodu.

+0

Współdzielone elementy mogą należeć do klasy bazowej, a następnie 'Coord' dziedziczą z tej klasy bazowej. – JSQuareD

+1

Muszę przyznać, że jestem zdezorientowany, dlaczego 'std :: enable_if' nie ma tutaj zastosowania, clang również to akceptuje i zachowuje się tak, jak się spodziewałem. – hmjd

+0

@hmjd ta odpowiedź wydaje się wyjaśniać: http://stackoverflow.com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function?lq=1 (Zgaduję, że GCC jest tutaj poprawne , ale mogę się mylić!) – Pubby

3

Można użyć tej metody opiera się na specjalizacji specjalizacji:

#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! 
} 
Powiązane problemy