对于容器中非多容器的简单情况,我有以下工作:
template <typename MultiContainer, typename SingleContainer>
void check (const MultiContainer& container, SingleContainer& v) {
if (std::is_same<MultiContainer, typename SingleContainer::value_type>::value)
return;
if (is_container<typename MultiContainer::value_type>::value) {
std::vector<typename MultiContainer::value_type::value_type> a; // Using vector for this first draft.
for (const auto& x : container)
std::copy (x.begin(), x.end(), std::back_inserter(a));
if (std::is_same<typename MultiContainer::value_type::value_type, typename SingleContainer::value_type>::value)
v = a;
// else check<decltype(a), SingleContainer>(a, v); // Won't compile
}
}
template <typename MultiContainer, typename SingleContainer>
SingleContainer extractFromMultiContainer (const MultiContainer& container) {
SingleContainer v;
check<MultiContainer, SingleContainer>(container, v);
return v;
}
int main() {
using Multi = std::list<std::vector<int>>;
const Multi multi = { {1,2,3}, {4,5}, {6,7,8,9} };
// using Multi = std::deque<std::list<std::vector<int>>>;
// const Multi multi = { { {1,2,3}, {4,5}, {6,7,8,9} }, { {10,11}, {12,13}, {14,15,16} } };
const auto v = extractFromMultiContainer<Multi, std::vector<int>>(multi);
for (int x : v) std::cout << x << ' '; // 1 2 3 4 5 6 7 8 9
}
但我无法在&#39;检查&#39;中获得所需的递归线。上面的函数用于处理容器中的容器容器(无论嵌套多深,都必须工作)。我在第一稿中使用vector作为SingleContainer(我稍后会尝试概括)。顺便说一句,我从stackoverflow Determine if a type is an STL container at compile time中的前一个线程获得了is_container的代码,因此我们可以将该部分视为理所当然:
template<typename T>
struct has_const_iterator {
private:
typedef char yes;
typedef struct { char array[2]; } no;
template<typename C> static yes test(typename C::const_iterator*);
template<typename C> static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
typedef T type;
};
template <typename T>
struct has_begin_end {
template<typename C> static char (&f(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
typename C::const_iterator(C::*)() const>::value, void>::type*))[1];
template<typename C> static char (&f(...))[2];
template<typename C> static char (&g(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
typename C::const_iterator(C::*)() const>::value, void>::type*))[1];
template<typename C> static char (&g(...))[2];
static bool const beg_value = sizeof(f<T>(0)) == 1;
static bool const end_value = sizeof(g<T>(0)) == 1;
};
template<typename T>
struct is_container : std::integral_constant<bool, has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value> {};
答案 0 :(得分:1)
据我了解,您需要一个通用的flatten
函数。您可以通过首先定义基本的平整器
template<typename T, bool cont = is_container<typename T::value_type>::value>
struct flattener {
template<typename In, typename Out>
static void flatten(In first, In last, Out res);
};
然后继续对容器
进行部分专业化template<typename T> struct flattener<T, true> {
template<typename In, typename Out>
static void flatten(In first, In last, Out res) {
for (; first != last; ++first)
flattener<typename T::value_type>::flatten(std::begin(*first), std::end(*first), res);
}
};
和非容器类型
template<typename T> struct flattener<T, false> {
template<typename In, typename Out>
static void flatten(In first, In last, Out res) {
std::copy(first, last, res);
}
};
您现在可以像
一样使用它std::vector<int> v1 = { 1, 2, 3 };
std::vector<int> res1;
flattener<decltype(v1)>::flatten(v1.begin(), v1.end(), std::back_inserter(res1));
std::vector<std::vector<int> > v2 = { {9, 8, 7}, {6, 5, 4}, {1, 2, 3} };
std::vector<int> res2;
flattener<decltype(v2)>::flatten(v2.begin(), v2.end(), std::back_inserter(res2));
std::vector<std::vector<std::vector<int> > > v3 = { { {9, 8}, {7, 6} },
{ {6, 5}, {4, 3} },
{ {1, 2}, {3, 4} } };
std::vector<int> res3;
flattener<decltype(v3)>::flatten(v3.begin(), v3.end(), std::back_inserter(res3));