10

型インデックスで指定されたデフォルトで構築された値を含む s を構築したいboost::variant- 型インデックスに独自の 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 に答える