std::变量,对于可能的类型,具有给定类型的数组的ptr.我可以存储更多只需键入的信息吗



我正在考虑使用std::variant来存储基本类型,如float、int、float2、bool2、bool4等。这很简单,但我也希望构建包含指向类型化数组的指针的变体对象。我提出了这个解决方案,它编译和运行时不会崩溃(这并不意味着没有错误(:

#include <variant>
#include <vector>
#include <iostream>
#include <algorithm>
struct float3
{
float x, y, z;
float3() : x(0), y(0), z(0) {}
float3(const float& r) : x(r), y(r), z(r) {}
};
int main()
{
typedef std::variant<float, float3, float3*> Variant;
std::vector<float3> v(3);
std::generate(v.begin(), v.end(), [n=0] () mutable { return ++n; });
Variant var(&v[0]);
if (float3** ptr = std::get_if<float3*>(&var)) {
std::cout << "this is a float3*: " << (*ptr)[0].x << std::endl;
}
else {
std::cout << "didn't recognize typen";
}
return 0;
};

然而,这样做会丢失一些我想与此特定变体类型一起存储的额外数据,例如数组的大小(例如,以字节为单位(。最好编写我自己的自定义Variant类并创建这样的构造函数:

class Variant 
{
public:
enum Type
{
...
FLOAT,
FLOAT2,
FLOAT3,
...
};
Variant(std::shared_ptr<void*>& ptr, Type type, size_t size, size_t stride, ...) : 
type(Type), 
data(new Data(ptr, size, stride, ...)) 
{}
std::shared_ptr<Data> data;
};

class Data

class Data
{
public:
Data(const std::shared_ptr<void*>& ptr, size_t nb, size_t stride, ...) :
ptr(ptr), nbytes(nb), stride(stride) ... {}
std::shared_ptr<void*> ptr;
size_t nbytes;
size_t stride;
...
}

或者我还能以某种方式使它与std::变体一起工作吗?如有任何建议,我们将不胜感激。

这个"指针加大小";类型自C++20以来就已经存在,它被称为std::span

您可以使用std::variant<float, float3, std::span<float3>>

如果您想要一个包含许多不同类型的数组,可以使用std::variant<std::span<float3>, std::span<float2>, std::span<bool2>, etc>。注意,您必须编写变体中的所有类型(可能想使其成为typedef(,但不必为每个类型编写特殊代码,因为您可以将visit与模板一起使用:

std::variant<std::span<float3>, std::span<float2>, std::span<bool2>> myVariant = ........;
// print all the elements. auto parameter makes a lambda with a template function.
// a separate copy is compiled for each type.
std::visit(myVariant, [](auto& span) {
for(auto& item : span)
std::cout << item << std::endl;
});

std::span用于其他人将删除的数组-如果您希望变体删除自己的内存,请使用std::vector

您实际上可以在一个类型中存储大量信息。例如,使用数组维度的整数范围。您不必实际使用数组的存储,只需声明指向此类数组的指针即可。

然后提取维度信息。下面是一个从指向数组的指针中提取三维的例子:

#include <type_traits>
#include <iostream>
#include <variant>
int main()
{
typedef int(*pa)[2][3][4];
int ia[2][3][4];
pa a{&ia};
std::variant<pa, float> v(&ia);
std::cout << std::extent<std::remove_cvref_t<decltype(*std::get<0>(v))>,0>::value << "n";
std::cout << std::extent<std::remove_cvref_t<decltype(*std::get<0>(v))>, 1>::value << "n";
std::cout << std::extent<std::remove_cvref_t<decltype(*std::get<0>(v))>, 2>::value << "n";
}
// outputs: 2,3,4

相关内容

最新更新