如何根据数组的大小启用/禁用函数?

Str*_*wie 4 c++ template-meta-programming c++-concepts c++20

我对 TMP 还很陌生,所以如果这是一个措辞不好的问题,请原谅我。

我正在尝试创建一个非常通用的数学 Vector 类来存储任意数量的组件,但默认为 3 并使用 float 作为其基本表示形式。因此,如果您默认构造这些向量之一,它将保存(0.0f,0.0f,0.0f)

这些值本身存储在 a 中std::array,我想创建访问器函数以方便使用。我目前有这个:

std::array<Type,SIZE> e;
Type x() const {return e.at(0);};
Type y() const {return e.at(1);};
Type z() const {return e.at(2);};
Run Code Online (Sandbox Code Playgroud)

我现在想做的是为第四个组件设置一个,w但只有当该数组的大小 >= 4 时才启用它。所以像这样:

template<class Type, std::enable_if<.......>>
Type w() const {return e.at(3);};
Run Code Online (Sandbox Code Playgroud)

这只是我认为它应该是什么样子的一个模糊的想法。我知道concept存在,但我也在努力为这种情况写一个。

康桓瑋*_*康桓瑋 9

有了概念,你就可以简单地做到

Type w() const requires (SIZE >= 4) {return e.at(3);};
Run Code Online (Sandbox Code Playgroud)


Rem*_*eau 5

在了解 C++20 概念之前,您可以执行以下操作:

template<typename Type = float, size_t SIZE = 3>
class Vector {
    std::array<Type, SIZE> e;
public:
    template<typename Dummy = void, std::enable_if_t<SIZE >= 3, Dummy>* = nullptr>
    Type x() const { return e[0]; };

    template<typename Dummy = void, std::enable_if_t<SIZE >= 3, Dummy>* = nullptr>
    Type y() const { return e[1]; };

    template<typename Dummy = void, std::enable_if_t<SIZE >= 3, Dummy>* = nullptr>
    Type z() const { return e[2]; };

    template<typename Dummy = void, std::enable_if_t<SIZE >= 4, Dummy>* = nullptr>
    Type w() const { return e[3]; };
};
Run Code Online (Sandbox Code Playgroud)
Vector v1;
v1.x();
v1.y();
v1.z();
//v1.w(); // ERROR
    
Vector<int, 4> v2; 
v2.x();
v2.y();
v2.z();
v2.w(); // OK
Run Code Online (Sandbox Code Playgroud)

在线演示


或者,您也可以这样做,就像 @Jarod42 建议的那样:

template<typename Type = float, size_t SIZE = 3>
class Vector {
    std::array<Type, SIZE> e;
public:
    template<size_t N = SIZE, std::enable_if_t<N >= 3>* = nullptr>
    Type x() const { return e[0]; };

    template<size_t N = SIZE, std::enable_if_t<N >= 3>* = nullptr>
    Type y() const { return e[1]; };

    template<size_t N = SIZE, std::enable_if_t<N >= 3>* = nullptr>
    Type z() const { return e[2]; };

    template<size_t N = SIZE, std::enable_if_t<N >= 4>* = nullptr>
    Type w() const { return e[3]; };
};
Run Code Online (Sandbox Code Playgroud)

在线演示

但是,这将允许用户显式地访问w()无效索引,例如:

Vector v1; // only has indexes 0..2
v1.w<5>(); // NO ERROR, but accesses index 3
Run Code Online (Sandbox Code Playgroud)