为什么不能在序列中放置多个元素?

abi*_*bir 5 c++ sequence c++11

C ++ 11引入emplace了在序列内部就位构造元素的功能。这是对insert元素进行复制或移动的补充。

但是,在的多个重载中insert,只有单个元素插入版本,

iterator insert( const_iterator p, T const& x);
iterator insert( const_iterator p, T&& x );
Run Code Online (Sandbox Code Playgroud)

有一个emplace版本,

template< class... Args > 
iterator emplace(const_iterator p, Args&&... x);
Run Code Online (Sandbox Code Playgroud)

是否有任何理由不允许n使用来就地构建元素emplace

虽然像

template< class... Args > 
iterator emplace(const_iterator p,size_type n,Args&&... x);
Run Code Online (Sandbox Code Playgroud)

就像相应的 insert

iterator insert(const_iterator p,size_type n,const_reference x);
Run Code Online (Sandbox Code Playgroud)

可能会与其他重载冲突,将构造函数参数用作tuple,或使用一些特殊标记(例如in_place_t可能会消除歧义)。

编辑 建议的功能emplace_n对于vector可能像下面给出的一个行为

template<class... Args>
iterator emplace_n(const_iterator p,size_type n,Args&&... x)
{
    size_type const offset = p - begin();
    if(capacity() < size()+n)
    {
        vector<T> v;
        v.reserve(size()+n);
        v.assign(make_move_iterator(begin(),make_move_iterator(end());
        swap(*this,v);
    }
    auto const sz = size();
    for(auto c = 0; c != n ; ++c)
    {
        emplace_back(x...); //can do forward only if n == 1
    }
    rotate(begin()+offset,begin()+sz,end());
    return iterator{begin() + offset};
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*ple 2

问题是没有简单的方法来确定一个元素的参数何时结束以及下一个元素的参数何时开始。您可以通过 s 传递参数tuple,就像 forpair的分段构造函数一样,最终得到一个像这样的辅助函数:

template<int... Is>
struct index_seq { };

template<int N, int... Is>
struct make_index_seq : make_index_seq<N - 1, N - 1, Is...> { };

template<int... Is>
struct make_index_seq<0, Is...> : index_seq<Is...> { };

template<class Cont, class Tup, int... Is>
void emplace_back_impl(Cont& c, Tup&& tup, index_seq<Is...>)
{
    using std::get;
    c.emplace_back(get<Is>(std::forward<Tup>(tup))...);
}

template<class Cont, class... Tups>
void emplace_multiple(Cont& c, Tups&&... tups)
{
    int const unpack[]{
        0, ((emplace_back_impl)(c, std::forward<Tups>(tups),
                                make_index_seq<
                                    std::tuple_size<typename std::remove_reference<Tups>::type>{}
                                >()), 0)...
    };
    static_cast<void>(unpack);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用该emplace_multiple函数来放置多个元素:

std::vector<std::string> xs;
emplace_multiple(xs, std::make_tuple("Hello, world!"), std::make_tuple(10, 'a'));
Run Code Online (Sandbox Code Playgroud)

请注意,这使用了emplace_back. emplace如果没有提前预留足够的空间,使用plus 迭代器来标记插入位置是危险的。这是因为emplaceandemplace_back可以使迭代器无效(至少对于vectors 而言),然后该函数不知道如何将新迭代器获取到您想要的位置。

演示在这里