构造一个包含变体类型索引中第 n 个类型值的 boost 变体?
Posted
技术标签:
【中文标题】构造一个包含变体类型索引中第 n 个类型值的 boost 变体?【英文标题】:Construct a boost variant containing a value of the nth-type in the variant type index? 【发布时间】:2012-02-16 14:33:50 【问题描述】:我想构造包含默认构造值的boost::variant
s,使用类型索引指定 - 无需在类型索引上编写我自己的 switch 语句。
我认为这必须以某种方式通过 MPL 实现?
为了澄清,索引不是编译时常量表达式。
用例是我需要构造一个变体,稍后将替换为包含正确值的变体,但此时我只知道类型索引。将其视为一个惰性反序列化问题。
【问题讨论】:
既然你提到了 MPL,我认为N
(类型索引)在编译时是已知的,但是惰性反序列化表明它可能只在运行时可用 --> 它是什么?
@MatthieuM。后者是不可能的。我希望是第一个,否则我的答案也毫无价值。
@MatthieuM。啊,好点:它只在运行时可用。
@Autopulated 这是否为您赢得了“本月检查的最奇怪的代码”奖或为什么获得赏金?
@pmr,事实上,我最终避免了创建空变体,这可能是明智的做法 - 我很感激你为解决我的疯狂问题付出的努力!跨度>
【参考方案1】:
您需要使用variant::types
typedef。这为您提供了一个与 MPL 兼容的序列,然后我们可以将其与 mpl::at
和一个模板一起使用来进行我们的投标。这就是诀窍:
#include <string>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
template<typename U, typename V>
void construct_in(V& v)
v = U();
// modern
// v = U;
int main()
typedef boost::variant<int, std::string> variant;
typedef boost::mpl::at<variant::types, boost::mpl::int_<1>>::type pos;
variant v;
// use type deduction
construct_in<pos>(v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
运行时变体如下:
#include <string>
#include <vector>
#include <functional>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/for_each.hpp>
typedef boost::variant<int, std::string> variant;
typedef variant::types types;
typedef std::vector< std::function<void(variant&)> > fvec;
template<typename U, typename V>
void construct_in(V& v)
v = U;
struct build_and_add
fvec* funcs;
template<typename T>
void operator()(T)
funcs->push_back(&construct_in<T, variant>);
;
int main()
variant v;
std::vector< std::function<void(variant&)> > funcs;
// cannot use a lambda, would need to be polymorphic
build_and_add f = &funcs;
boost::mpl::for_each<types>(f);
// this is runtime!
int i = 1;
funcs[i](v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
这有点神秘,需要使用可变参数进行一些调整 参数是真正通用的,但它会做你想要的。其他人需要弄清楚这是否会导致显着 代码爆炸。
【讨论】:
很抱歉澄清类型索引是运行时的,但我认为这个答案没有用 - 可以扩展它以在运行时在 N 个常量索引之间切换,其中只有 N 在编译时是固定的(甚至可以从变体中提取出来,也许?) @Autopulated 不是真的,但一些黑魔法可能会有所帮助。想想我们用于构建的模板。我们可以在编译时生成所有这些模板,并将它们作为std::function
对象存储在一个向量中,并在运行时使用这个向量来查找我们想要构建的内容。我会尝试把一些东西放在一起,但我不知道在代码爆炸等方面会有多好。
@pmr:我的下意识反应是使用递归,但是指向函数的向量(或数组,因为 N 是常数)似乎提供了更好的性能保证(不依赖于最终的尾递归)。您可能仍然需要递归来初始化向量,但它是一次性的。
@MatthieuM。对于这些事情,我是mpl::for_each
的忠实粉丝。使用 MPL 编写递归模板函数总是有点棘手,因为它们的序列不是真正的可变参数模板。
@MatthieuM。我更喜欢临时函子的引用指针,消除了对构造函数的需要。关于订单:我找不到任何明确的内容,但for_each
最多需要ForwardSequence
,因此不应允许它做任何其他事情。以上是关于构造一个包含变体类型索引中第 n 个类型值的 boost 变体?的主要内容,如果未能解决你的问题,请参考以下文章
python面试题-输入一个由n个大小写字母组成的字符,按Ascii码值从小到大排序,查找字符串中第k个最小Ascii码值的字母