We can create some template infrastructure to allow creation of vectors through optional concatenation of objects and other vectors.
This is very much a first cut:
#include <utility> #include <vector> namespace extended { template<class T> struct appender { template<class V, class A, class Arg> void operator()(std::vector<V, A>& vec, Arg&& arg) const { vec.push_back(std::forward<Arg>(arg)); } }; template<class V2, class A2> struct appender<std::vector<V2, A2>> { template<class V, class A, class X> void operator()(std::vector<V, A>& vec, X&& arg) const { vec.insert(end(vec), begin(std::forward<X>(arg)), end(std::forward<X>(arg))); } }; template<class V, class A, class T> auto append(std::vector<V, A>& target, T&& x) -> decltype(auto) { auto op = appender<std::decay_t<T>>(); op(target, std::forward<T>(x)); return target; } } template<class T, class...Args> auto make_vector(Args&&...args) { using extended::append; std::vector<T> result; using expand = int[]; expand {0, (append(result, std::forward<Args>(args)), 0)... }; return result; } class Foo { public: Foo(int value){m_v=value;} private: int m_v = 0; }; int main() { auto v1 = make_vector<Foo>(Foo(1)); //ok auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok auto v3 = make_vector<Foo>(Foo(3), v2); //ok }
Of course, by looking for common interfaces we can start to push the boundaries a little:
#include <utility> #include <iterator> #include <vector> #include <list> #include <set> namespace extended { // The general case of an appender. // simply calls emplace_back template<class T, class Diff = void> struct appender { template<class V, class A, class Arg> void operator()(std::vector<V, A>& vec, Arg&& arg) const { vec.emplace_back(std::forward<Arg>(arg)); } }; // specific specialisation for an appender where the // source object supports begin() and end() (i.e. a container) // template<class T> struct appender < T, decltype( std::begin(std::declval<T>()), std::end(std::declval<T>()), void() ) > { template<class V, class A, class X> void operator()(std::vector<V, A>& vec, X&& arg) const { vec.insert(std::end(vec), std::begin(std::forward<X>(arg)), std::end(std::forward<X>(arg))); } }; template<class V, class A, class T> auto append(std::vector<V, A>& target, T&& x) -> decltype(auto) { auto op = appender<std::decay_t<T>>(); op(target, std::forward<T>(x)); return target; } } template<class T, class...Args> auto make_vector(Args&&...args) { using extended::append; std::vector<T> result; using expand = int[]; expand {0, (append(result, std::forward<Args>(args)), 0)... }; return result; } class Foo { public: Foo(int value){m_v=value;} bool operator<(const Foo& r) const { return m_v < r.m_v; } private: int m_v = 0; }; int main() { auto v1 = make_vector<Foo>(Foo(1)); //ok auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok auto v3 = make_vector<Foo>(Foo(3), v2); //ok auto v4 = make_vector<Foo>(Foo(1), std::list<Foo> { Foo(2), Foo(3) }, make_vector<Foo>(4, make_vector<Foo>(8, 9, 10)), std::set<Foo> {Foo(6), Foo(7) }); // bizzare but ok }