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

标签 c++ stl containers 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'});

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式建筑。标准库容器将此类构造转发给 allocator_traits<Alloc>::construct<T> ,这应该是一个可变参数函数。如果Alloc没有construct成员函数,然后 allocator_traits::construct将简单地使用 placement new with ()初始化语法。

显然,这不允许您通过 emplace 进行聚合初始化.但是,您可以有效地实现 the solution suggested by 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)...};
}

关于c++ - 如何将聚合支持到 STL 或类似 STL 的库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41385190/

相关文章:

c++ - 如何在没有 nvcc 的情况下在编译时获取 CUDA 工具包版本?

c++ - 获取类似 STL 的嵌套容器中的元素总数

c++ - 如何根据元素数量选择 max_load_factor?

ios - 如何在自定义容器 View Controller 中实现交互式转换

c++ - 析构函数好像叫 'early'

c++ - win32 全选编辑 ctrl(文本框)

java - 文件处理中的 Apache Avro

c++ - matrix.size() 和 matrix[0].size() 有什么区别?

html - 包裹元素上的 CSS 容器宽度

ios - 当嵌入 View 尺寸改变时,如何用动画改变容器 View 尺寸?