10

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

我想这一定是可能的,不知何故,与 MPL?

不过要澄清一下,索引不是编译时常量表达式。

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

4

1 回答 1

13

您需要使用variant::typestypedef。这为您提供了一个与 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;
}

它有点神秘,需要对可变参数进行一些调整才能真正通用,但它可以满足您的需求。其他人需要弄清楚这是否会导致严重的代码爆炸。

于 2012-02-16T14:40:18.460 回答