根据编译时参数使方法可用

Making a method available depending on a compile-time argument

本文关键字:方法 参数 编译      更新时间:2023-10-16

是否有一种方法来编译一个方法,取决于模板参数?我试图创建一个坐标类,可以处理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];
    }
};

我想做的是隐藏维度2的z()的存在,这样

Coord<int, 2> ci2(0,0);
ci2.z() = 3;   // shouldn't compile
如果不使用static_assert,

不能编译。我看到过很多关于std::enable_if的问题,但据我所知,它是用来启用或禁用特定的重载的。

问题是:是否有一种方法可以使方法可用或不依赖于编译时参数?

例如,您可以将函数声明为模板,并像这样使用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];
    }
};

您可以使用专门化:

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

您可以将共享成员提升到单独的结构中,以防止代码重复。

您可以使用这种基于专门化的方法:

#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!
}