将类转换为固定长度的浮点数组

Convert class to fixed-length float array

本文关键字:数组 转换      更新时间:2023-10-16

如何将以下类转换为固定长度的浮点数组?

class Vertex
{
public:
    Vertex( float x = 0,
            float y = 0,
            float z = 0)
    : x(x), y(y), z(z) {}
    float x, y, z;
};

例如,我想像这样使用它:

Vertex v(0, 1, 0);
float arr[3] = v; // How to convert here?

谢谢!


编辑:

在发布此问题之前,我应该添加一些背景信息。

我之所以使用 C 样式数组,是因为我想将高级顶点对象组合成一个顶点数组,以便使用 OpenGL 进行渲染,据我所知,这需要原始数组(float[3])或结构的集合。

为此,我认为user2079303的答案是最佳选择。但是,如果存在更优雅的解决方案,那就更好了。:)

#include <iostream>
#include <array>
using namespace std;
class Vertex
{
public:
    Vertex( float x = 0,
            float y = 0,
            float z = 0)
    : x(x), y(y), z(z) {}
    operator array<float, 3>() const {
        return {x,y,z};
    }
    /* See @user2079303's answer for a compile-time check of the array dimension */
    void fillArray(float arr[3]) {
        arr[0] = x;
        arr[1] = y;
        arr[2] = z;
    }
    float x, y, z;
};
int main() {
    Vertex v(1,1.4,2);
    array<float, 3> arr = v;
    float arr2[3];
    v.fillArray(arr2);
    for (int i = 0; i < 3; i++) {
        cout << arr[i] << " " << arr2[i] << endl;
    }
    return 0;
}

现场演示

std::array 与使用 C 样式数组一样高效,不会损失任何性能。您也可以改用std::vector

你不能只返回和复制一个数组,即使是在 C 中。这就是为什么如果你绝对想使用 C 数组,你必须有一个像 fillArray 这样的函数。

不能转换为(原始)数组,因为强制转换运算符必须返回一个数组,这在 c++ 中是不允许的。此外,数组无论如何都无法进行复制初始化。

你可以做的是定义一个数组,并将其传递给一个函数,该函数根据对象的内容填充数组:

void Vertex::fill_arr(float (&arr)[3]) {
    arr[0] = x;
    arr[1] = y;
    arr[2] = z;
}
// usage
Vertex v(1, 2, 3);
float arr[3];
v.fill_arr(arr);

另一种选择是使用可以正常返回和复制初始化的std::array

你有很多选择,你选择它在很大程度上取决于上下文。以下是"转换"顶点的四种不同方法:

class Vertex
{
public:
    Vertex(float x = 0,
        float y = 0,
        float z = 0)
        : x(x), y(y), z(z) {}
    operator array<float, 3> () const {
        return {x, y, z};
    }
    array<float, 3> array_copy() const {
        return {x, y, z};
    }
    unique_ptr<float[]> c_array_copy() const {
        return unique_ptr<float[]>(new float[3]{ x, y, z });
    }
    void copy_into(float in[3]) const {
        in[0] = x;
        in[1] = y;
        in[2] = z;
    }
    float x, y, z;
};

首先,您可以使用 () 运算符强制转换类:

cout << "Direct access" << endl;
auto as_array = (array<float, 3>)vertex;
cout << as_array[0] << as_array[1] << as_array[2] << endl;

其次,你可以让array_copy()将语义复制到一些工作中:

cout << "Get a copy" << endl;
auto as_copy = vertex.array_copy();
cout << as_copy[0] << as_copy[1] << as_copy[2] << endl;

第三,您可以获得一个更 c 风格的数组副本,其中包含指向动态分配数组的唯一指针:

cout << "Get a c-style copy" << endl;
auto as_c_copy = vertex.c_array_copy();
cout << as_c_copy[0] << as_c_copy[1] << as_c_copy[2] << endl;

最后,您可以复制到 out 参数中:

cout << "Copy onto an out-parameter" << endl;
float copied[3];
vertex.copy_into(copied);
cout << copied[0] << copied[1] << copied[2] << endl;

正如我所说,您选择哪个实际上取决于上下文和性能要求。

请注意,在任何情况下都不能只返回 c 样式数组。

您可以定义转换运算符来构造数组。此外,我建议使用std::array而不是原始数组。

#include <array>
class Vertex
{
public:
    Vertex(float x = 0.0f, float y = 0.0f, float z = 0.0f)
    : x(x), y(y), z(z)
    {}
    float x;
    float y;
    float z;
    operator const std::array<float, 3>() const
    {
        return {x, y, z};
    }
};
int main()
{
    Vertex v(0.0f, 1.0f, 0.0f);
    std::array<float, 3> arr = v;
}