构造一个boost变量,其中包含变量类型索引中的第n个类型的值?

时间:2012-02-16 14:33:51

标签: c++ boost boost-variant

我想构造包含使用类型索引指定的默认构造值的boost::variant - 而不在类型索引上编写我自己的switch语句。

我认为必须才能以某种方式使用MPL?

尽管如此,索引不是编译时常量表达式。

用例是我需要构造一个变体,稍后将替换为包含正确值的变量,但此时我只知道类型索引。把它想象成一个懒惰的反序列化问题。

1 个答案:

答案 0 :(得分:13)

您需要使用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;
}

这有点神秘,需要进行一些可变的调整 参数是真正的通用,但它做你想要的。其他人需要弄清楚这是否会产生重大影响 代码爆炸。

相关问题