4

Valueのベクトルからに変換するために、以下の関数をどのように実装できContainerますか?valuesのすべてのメンバーが同じタイプではない場合、つまり、ベクトルに文字列とintが混在している場合は、主張したいと思います。これは、関数の戻り値がastd::vector<int>または。のいずれかであるためstd::vector<std::string>です。

typedef boost::variant<int, std::string> Value;
typedef boost::variant<std::vector<int>, std::vector<std::string> > Container;

Container valuesToContainer(const std::vector<Value>& values) 
{
    return Container();
}
4

2 に答える 2

3
  struct converter_visitor : public boost::static_visitor<Container>
  {

         const std::vector<Value> & _cont;
         converter_visitor(const std::vector<Value> &r) : _cont(r) {}

         template<class T>
         Container operator()(const T &) const {
                  std::vector<T> ans;
                  ans.reserve(_cont.size());
                  for (int i=0;i < _cont.size();++i)
                         ans.push_back( boost::get<T>(_cont[i]));
                  return ans;
         }
   };

   Container valuesToContainer(const std::vector<Value> & values) {
         //assuming !values.empty()
         return boost::apply_visitor( converter_visitor(values),values.front());
   }

bad_getこれにより、のすべての要素がvalues同じタイプではないにしても、がスローされます。

于 2013-03-21T13:13:24.943 に答える
1

これは便利かもしれません、多分:

template <typename... T> using VariantVector = std::vector<boost::variant<T...>>;
template <typename... T> using VectorPack    = std::tuple<std::vector<T>...>;

template <typename... T>
    VectorPack<T...> splitVectors(VariantVector<T...> const &values);

OPによって要求される関数との違いは、すべての要素タイプが一致しない場合に「エラー」の代わりに、ベクトルのタプル( "VectorPack")を返し、必要なものを簡単に選択できることです。

デモプログラム:

#include <boost/variant.hpp>
#include <boost/variant/static_visitor.hpp>
#include <tuple>
#include <vector>

using std::get;

template <typename... T> using VariantVector = std::vector<boost::variant<T...>>;
template <typename... T> using VectorPack    = std::tuple<std::vector<T>...>;

namespace detail
{
    template <typename T>
    struct VectorSplitterMixin {
        void operator()(T const& v) { _bucket.push_back(v); }
        std::vector<T> _bucket;
    };

    template <typename... T>
        struct VectorSplitter : boost::static_visitor<>, VectorSplitterMixin<T>...
    {
        typedef VectorPack<T...> product_t;
        product_t product() {
            return product_t { std::move(static_cast<VectorSplitterMixin<T>*>(this)->_bucket)... };
        }
    };
}

template <typename T> struct X;

template <typename... T>
    VectorPack<T...> splitVectors(VariantVector<T...> const &values)
{
    auto splitter = detail::VectorSplitter<T...>();
    for (auto& val : values)
        boost::apply_visitor(splitter, val);
    return splitter.product();
}

int main()
{
    typedef boost::variant<int, std::string> Value;
    typedef boost::variant<std::vector<int>, std::vector<std::string> > Container;

    const std::vector<Value> vec { 42, "hello world", 1, -99, "more" };

    auto vectorPack = splitVectors<int, std::string>(vec);

    for (auto i : get<0>(vectorPack))
        std::cout << "int:" << i << ", ";
    std::cout << "\n";

    for (auto& s : get<1>(vectorPack))
        std::cout << "string:" << s << ", ";
    std::cout << "\n";
}

印刷:

int:42, int:1, int:-99, 
string:hello world, string:more, 
于 2013-03-21T14:21:48.447 に答える