2013-03-21 112 views
4

如何實現以下功能將Value的向量轉換爲Container?如果不是values的所有成員都是相同類型,即,如果矢量包含字符串和整數的組合,我希望斷言。這是因爲該函數的返回值是std::vector<int>std::vector<std::string>轉換boost :: variant類型的std :: vector

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(); 
} 
+0

你在問。你想知道如何檢查元素是否都是同一類型?或者你問如何做轉換?你試過什麼了?你知道'boost :: apply_visitor'嗎? – sellibitze 2013-03-21 13:13:42

回答

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所有元素都是同一類型的。

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, 
相關問題