Using the semantics of container movement and elementary initialization

It is often seen that examples of using STL algorithms are illustrated by containers with list initialization, such as:

std::vector< int > v{1, 2, 3, 4};

But when this approach is used for (heavy) classes (as opposed to ints), it implies excessive copy operations from them, even if they are passed by rvalue (moved to), because the std::initializer_listexample above only provides const_iterators.

To solve this problem, I use the following approach (C ++ 17):

template< typename Container, typename ...Args >
Container make_container(Args &&... args)
{
    Container c;
    (c.push_back(std::forward< Args >(args)), ...);
    // ((c.insert(std::cend(c), std::forward< Args >(args)), void(0)), ...); // more generic approach
    return c;
}

auto u = make_container< std::vector< A > >(A{}, A{}, A{});

But this becomes unsatisfactory when I do the following:

A a;
B b;
using P = std::pair< A, B >;
auto v = make_container< std::vector< P > >(P{a, b}, P{std::move(a), std::move(b)});

(, A B , ), , undefined ++. :

template< Container >
struct make_container
{

    template< typename ...Args >
    make_container(Args &&... args)
    {
        (c.push_back(std::forward< Args >(args)), ...);
    }

    operator Container () && { return std::move(c); }

private :

    Container c;

};

A a; B b;
using P = std::pair< A, B >;
using V = std::vector< P >;
V w = make_container< V >{P{a, b}, P{std::move(a), std::move(b)}};

, , - , .

? , ? ( ++ 11, ++ 14, ++ 1z)?

+4
2

:

template<class Container, std::size_t N>
inline Container make_container(typename Container::value_type (&&a)[N])
{
    return Container(std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)));
}

:

make_container<std::vector<A>>({A(1), A(2)})

-, std::initializer_list, , .

:

  • : Container ctor, (, std::vector )
  • Eval order: it list-initialization

DEMO

+1

?

, . , std::move . . . , . , . , .

, .

A a; A b;
using V = std::vector< A >;
A c {a};
V v = make_container< V >{std::move(a), b, std::move(c)};
+1

All Articles