如何将聚合支持到STL或类似STL的库中

Ori*_*ent 1 c++ containers stl aggregate c++17

如何在(例如)STL容器中引入聚合初始化的支持以正确构建它们?我的意思是:

struct A { int i; char c; };
std::list< A > l; // empty
l.insert(std::memberwise, 1, '2');
// <=> l.insert({1, '2'});
Run Code Online (Sandbox Code Playgroud)

std::memberwise是一个可能的标签,就像在STL中已经存在一样std::piecewise_construct,std::allocator_arg等等.

从理论上讲,以这种方式扩展STL容器是否可行?有没有最好的方法("STL-way")来做到这一点?它看起来怎么样?

问题是关于界面设计和(内部)实现的可能性(不是细节).

我确定容器使用::new (static_cast< void * >(pstorage) value_type(std::forward< Args >(args)...);内部的东西.我确定,用括号替换括号会破坏更改.因为非缩小,例如

另外

l.insert({1, '2'});评论中一般提到可能会导致过度移动value_type.很可能这一步将由任何现代编译器优化,但无论哪种方式都有过多的花括号.

Nic*_*las 5

你应该使用emplace-style结构.标准库容器将这种结构转发到allocator_traits<Alloc>::construct<T>,这预计是一种可变功能.如果Alloc没有construct成员函数,那么allocator_traits::construct只需使用()初始化语法的placement new .

显然,这不允许你通过聚合初始化emplace.但是,您可以通过提供自己的分配器来有效地实现LWG 2089建议的解决方案std::allocator,该分配器可能来自,具有自己的construct方法.你construct应该只new(p) T(...)is_constructible<T, ...>::value真实的情况下使用.如果不是,那么你使用new(p) T{...}.

在C++ 17中,这实际上并不难写:

template< class U, class... Args >
void construct( U* p, Args&&... args )
{
    if constexpr(std::is_constructible_v<U, Args...>)
        ::new((void*)p) U(std::forward<Args>(args)...);
    else
        ::new((void*)p) U{std::forward<Args>(args)...};
}
Run Code Online (Sandbox Code Playgroud)