#include #include #include #include #include #include #include namespace details { template auto flatten(Container const& container, int, int) -> decltype( std::begin(container), std::vector{} ); template std::vector flatten(T const& value, int, float); template auto flatten(Iterator const& it, float, float) -> decltype( *it, std::vector{} ); template std::vector flatten(T const& value, int, float) { return { value }; } template auto flatten(Iterator const& it, float, float) -> decltype( *it, std::vector{} ) { return flatten(*it, 0, 0); } template auto flatten(Container const& container, int, int) -> decltype( std::begin(container), std::vector{} ) { std::vector result { }; for (auto&& element : container) { std::vector subresult { flatten(element, 0, 0) }; std::copy(std::begin(subresult), std::end(subresult), std::back_inserter(result)); } return result; } } template std::vector flatten(Container const& container) { return details::flatten(container, 0, 0); } int main() { { assert( flatten(5) == std::vector { 5 } ); } { std::vector> v { { 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9 } }; std::vector expected { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; assert( flatten(v) == expected ); } { std::vector data { 'a', 'b', 'c' }; using iterator = std::vector::iterator; std::vector> v { { std::begin(data), std::begin(data), std::begin(data) }, { std::begin(data) + 1 }, { std::begin(data) + 2, std::begin(data) + 2 } }; std::vector expected { 'a', 'a', 'a', 'b', 'c', 'c' }; assert( flatten(v) == expected ); } { std::vector>>> v { { { { 1.2, 3.45, 6.0 }, { 7.8, 9.10 }, }, { { 11.1213, 14.0 }, { 15.16, 17.18, 19.20 }, { 21.22 } }, }, { {}, { { }, { 23.2425 }, { } }, {} }, }; std::vector expected { 1.2, 3.45, 6.0, 7.8, 9.10, 11.1213, 14.0, 15.16, 17.18, 19.20, 21.22, 23.2425 }; assert( flatten(v) == expected ); } { int x { 5 }; std::vector v { &x }; assert(( flatten(v) == std::vector{ 5 } )); assert(( flatten(v) == std::vector{ &x } )); } }