Creating a method based on a compile-time argument

Is there a way to compile the method or not, depending on the template argument? I am trying to create a Coordinate class that can handle 2, 3 or more dimensions. I want to provide acces methods like x() , y() and z() , but I would like the z() method to be available only if the size is greater than 3. At the moment (as you can see below) I use a static_assert to prevent the use of z() for coordinates of dimension 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]; } }; 

What I would like to do is hide the existence of z() for dimension 2, so this

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

does not compile without using static_assert. I saw a lot of questions around std :: enable_if, but as I understand it, it is used to enable or disable certain overloads.

Question: is there a way to make the method available or not depending on the compile-time argument?

+6
source share
3 answers

For example, you can declare your function as a template and use std::enable_if like this

 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]; } }; 
+8
source

You can use the specialization for this:

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

You can put common members in a separate structure to prevent code duplication.

+6
source

You can use this approach based on specialization specialization:

 #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! } 
+3
source

All Articles