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.很可能这一步将由任何现代编译器优化,但无论哪种方式都有过多的花括号.
你应该使用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)
| 归档时间: |
|
| 查看次数: |
94 次 |
| 最近记录: |