给定变量类型:
using Variant = std::variant<bool, char, int, float, double, std::string>;
Run Code Online (Sandbox Code Playgroud)
和一个元组类型,其中包含限于该变量类型的元素(可能有重复和省略,但不能有其他类型):
using Tuple = std::tuple<char, int, int, double, std::string>;
Run Code Online (Sandbox Code Playgroud)
如何在运行时实现通过给定索引获取和设置元组元素的方法为Variant的方法:
Variant Get(const Tuple & val, size_t index);
void Set(Tuple & val, size_t index, const Variant & elem_v);
Run Code Online (Sandbox Code Playgroud)
我的代码中有两个实现,但我有一个更好的印象。我的第一个实现使用std::function第二个构建一个由一些Accessor指针组成的数组,这些指针对移动和复制对象施加了限制(因为它的地址更改了)。我想知道是否有人知道实现此目标的正确方法。
编辑1:
以下示例可能阐明了我的意思:
Tuple t = std::make_tuple(1, 2, 3, 5.0 "abc");
Variant v = Get(t, 1);
assert(std::get<int>(v) == 2);
Set(t, 5, Variant("xyz"));
assert(std::get<5>(t) == std::string("xyz"));
Run Code Online (Sandbox Code Playgroud)
我将继续我的主题,建议对所有元编程事物使用Boost.Mp11,因为它总有一个函数。在这种情况下,我们要mp_with_index。该函数将运行时索引提升为编译时索引。
Variant Get(Tuple const& val, size_t index)
{
return mp_with_index<std::tuple_size_v<Tuple>>(
index,
[&](auto I){ return Variant(std::get<I>(val)); }
);
}
Run Code Online (Sandbox Code Playgroud)
鉴于在OP中,元组和变体的索引甚至不对齐,因此Set需要实际访问Variant而不是依赖索引。我在is_assignable这里使用约束,但是可以对其进行调整以适合该问题(例如,可能应该是is_same)。
void Set(Tuple& val, size_t index, Variant const& elem_v)
{
mp_with_index<std::tuple_size_v<Tuple>>(
index,
[&](auto I){
std::visit([&](auto const& alt){
if constexpr (std::is_assignable_v<
std::tuple_element_t<Tuple, I>,
decltype(alt)>)
{
std::get<I>(val) = alt;
} else {
throw /* something */;
}
}, elem_v);
});
}
Run Code Online (Sandbox Code Playgroud)
如果您要求中的每个类型仅在中Tuple出现一次Variant,并且您只想直接从该类型进行赋值而不进行任何转换,则可以简化为:
void Set(Tuple& val, size_t index, Variant const& elem_v)
{
mp_with_index<std::tuple_size_v<Tuple>>(
index,
[&](auto I){
using T = std::tuple_element_t<Tuple, I>;
std::get<I>(val) = std::get<T>(elem_v);
});
}
Run Code Online (Sandbox Code Playgroud)
如果变体不与该类型结合使用,则会抛出该异常。
| 归档时间: |
|
| 查看次数: |
177 次 |
| 最近记录: |