0

我有一个 std::variant,它有两个不同的结构作为替代。现在我需要用另一种选择的数据填充它(我在运行时知道),但它必须以某种方式,可以单独在结构中写入元素。显然,这是行不通的:

struct ContainerOne {
    uint8_t x;
};

struct ContainerTwo {
    uint8_t y;
    uint8_t z;
};

std::variant<ContainerOne, ContainerTwo> ContainerCollection;                   // CHOICE
ContainerCollection.x = 20;   // Error

还有另一种方法可以实现这一目标吗?如果我知道我想写的替代方案,也许一种方法可以告诉变体它具有哪种结构或类似的东西?

我能弄清楚的唯一方法是为变体的内存空间制作一个强制引用并使用它来写入它。问题是这没有使用变体的方法,因此不会自动设置索引。同样以相同的方式设置索引也很困难,因为索引的大小因不同的变体而异(有时是一个字节,有时是 8 个字节):

ContainerOne &ContainerOneRef = *(reinterpret_cast<ContainerOne*>(&ContainerCollection));

uint8_t* newptr = reinterpret_cast<uint8_t*>(&ContainerCollection) + sizeof(ContainerCollection) - 0x01; // jump to the end of variant and one byte back, in the case the index is 1 Byte
*newptr = 0x01;

ContainerOneRef.x = 20;

或者有没有办法找出索引的大小?

4

3 回答 3

0

您需要在运行时进行某种调度,以根据活动元素(成员函数index())的返回索引选择适当的值。例如,如果我们为每种类型提供选择并使用std::get

#include <iostream>
#include <cstdlib>
#include <variant>

struct ContainerOne {
    uint8_t x;
};

struct ContainerTwo {
    uint8_t y;
    uint8_t z;
};
              
using ContainerType = std::variant<ContainerOne, ContainerTwo>;

void init_ContainerOne(ContainerType& v) {
    std::get<ContainerOne>(v).x = 20;
    std::cout << __PRETTY_FUNCTION__ << "\n";
}

void init_ContainerTwo(ContainerType& v) {
    std::get<ContainerTwo>(v) = {};
    std::cout << __PRETTY_FUNCTION__ << "\n";
}

decltype(&init_ContainerOne) dispatch[] =  { init_ContainerOne,  init_ContainerTwo };


int main()
{
   std::variant<ContainerOne, ContainerTwo> container  = ContainerOne{};
    
   dispatch[container.index()](container);
}

C++17 提供std::visit让基础架构更易于构建

于 2021-07-15T07:32:54.580 回答
0

阅读std::get

你的代码变得像

struct ContainerOne {
    uint8_t x;
};

struct ContainerTwo {
    uint8_t y;
    uint8_t z;
};
int main()
{   
    std::variant<ContainerOne, ContainerTwo> ContainerCollection; 
    ContainerCollection = ContainerOne{1};
    std::get<ContainerOne>(ContainerCollection).x = 2;
    std::cout << std::get<ContainerOne>(ContainerCollection).x;
    return 0;
}

PS而且你必须记住std::variant,如果你没有明确指定结构的类型(你调用一个空的构造函数),那么变量由第一种类型的默认构造函数初始化,所以在你的情况下它是ContainerOne

于 2021-07-15T07:17:00.213 回答
0

我不确定,但您似乎想使用 std::get。

struct ContainerOne {
    uint8_t x = 0;
};

struct ContainerTwo {
    uint8_t y = 0;
    uint8_t z = 0;
};

int main() {


std::variant<ContainerOne, ContainerTwo> ContainerCollection;

ContainerCollection = ContainerOne();

std::get<ContainerOne>(ContainerCollection).x = 1;

ContainerCollection = ContainerTwo();

std::get<ContainerTwo>(ContainerCollection).y = 2;
std::get<ContainerTwo>(ContainerCollection).z = 3;

}
于 2021-07-15T07:23:25.593 回答