将范围内的 `polymorphic_allocator` 与 `boost::circular_buffer` 一起使用失败
Using scoped `polymorphic_allocator` with `boost::circular_buffer` fails
背景
我想将 boost::circular_buffer
与作用域 C++17 std::pmr::polymorphic_allocator
一起使用。 IE。我想要将外部容器的相同分配器用于内部容器。
旁注:
boost::circular_buffer
is allocator-aware 并且以下断言为真:
static_assert(std::uses_allocator_v<
boost::circular_buffer<int, std::pmr::polymorphic_allocator<int>>,
std::pmr::polymorphic_allocator<int>>);
在这种情况下,我有一个循环缓冲区向量。使用默认分配器,它将是 std::vector<boost::circular_buffer<T>>
类型
使用std::pmr::polymorphic_allocator
我表示为:
#include <vector>
#include <memory_resource>
#include <boost/circular_buffer.hpp>
template<class T>
using Alloc = std::pmr::polymorphic_allocator<T>;
using Inner = boost::circular_buffer<int, Alloc<int>>;
using Outer = std::pmr::vector<Inner>;
使用这些别名,Inner
可以与 std::pmr::polymorphic_allocator
一起使用,但不能作为 Outer
.
的元素
以下作品:
Outer::allocator_type alloc1; // Allocator type used by Outer to allocate Inner
Inner::allocator_type alloc2; // Allocator type used by Inner to allocate ints
// circular_buffer works if used directly with polymorphic_allocator
Inner inner1; // default arg OK
Inner inner2(alloc1); // pmr with allocator as last argument, also implicitly converts OK
Inner inner3(1, alloc2); // pmr with allocator as last argument OK
// Use to instantiate member functions
inner1.set_capacity(16);
inner2.set_capacity(16);
inner3.set_capacity(16);
inner1.push_back(1);
inner2.push_back(1);
inner3.push_back(1);
但是当用作作用域分配器时(std::pmr::polymorphic_allocator
支持 without any need for std::scoped_allocator_adapter
) it fails to compile with difficult to interpret errors。
其中一个错误是 static_assertion
失败,因为 circular_buffer
无法使用提供的分配器构造,我正在复制(可能不正确)但没有在此处触发断言:
Outer v;
/* Statically asserts because Inner is not constructible
c++/12.0.0/bits/uses_allocator.h:98:60:error: static assertion failed: construction with an allocator must be possible if uses_allocator is true
98 | is_constructible<_Tp, _Args..., const _Alloc&>>::value,
[with
_Args = {};
_Tp = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >;
_Alloc = std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > >;
std::vector<_Tp, _Alloc>::reference = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >&]
*/
// Note: Adding prefix `A` to make names allowed
using A_Tp = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >;
using A_Alloc = std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > >;
static_assert(std::is_constructible<Inner, const A_Alloc&>::value); // OK
static_assert(std::is_same_v<Inner, A_Tp>); // OK
static_assert(std::is_same_v<typename Outer::allocator_type, A_Alloc>); // OK
v.emplace_back(); // ERROR
v.emplace_back(1); // ERROR
编译器浏览器link
https://godbolt.org/z/4n1Gjhqxh
问题
- 我在这里使用
std::pmr::polymorphic_allocator
不正确吗?
- 编译器试图通过错误告诉我什么?
- 为什么从
emplace_back
使用时复制的断言没有失败?
std::pmr::polymorphic_allocator
是否引入了任何使其与 boost::circular_buffer
不兼容的 new/additional 分配器要求,或者这是 boost::circular_buffer
的问题?
编辑
- 在 STL 模板参数的复制中添加了前缀
A
。
第一条错误消息指出这无效:
std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > > alice;
boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > bob(
std::declval<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >>(),
alice
);
它似乎在尝试复制循环缓冲区,同时将分配器作为第二个参数传入。
circular_buffer
的重载不接受这两个参数。
static_assert(std::is_constructible_v< Inner, Inner, Alloc<int>& >);
这基本上就是失败的断言。
作用域分配器协议要求该类型的每个构造函数都有一个相应的分配器扩展版本(通过将分配器参数附加到参数列表,或者通过在前面加上两个参数- allocator_arg_t
后跟分配器)。
这包括复制和移动构造函数,boost::circular_buffer
似乎没有为其提供分配器扩展版本。对这两个分配器扩展的构造函数的要求特别在 C++11 分配器感知容器要求中。
特别是对于 vector
,emplace_back
需要能够在重新分配时复制或移动现有元素,这就是为什么它需要分配器扩展的 copy/move 构造函数。
背景
我想将 boost::circular_buffer
与作用域 C++17 std::pmr::polymorphic_allocator
一起使用。 IE。我想要将外部容器的相同分配器用于内部容器。
旁注:
boost::circular_buffer
is allocator-aware 并且以下断言为真:
static_assert(std::uses_allocator_v<
boost::circular_buffer<int, std::pmr::polymorphic_allocator<int>>,
std::pmr::polymorphic_allocator<int>>);
在这种情况下,我有一个循环缓冲区向量。使用默认分配器,它将是 std::vector<boost::circular_buffer<T>>
使用std::pmr::polymorphic_allocator
我表示为:
#include <vector>
#include <memory_resource>
#include <boost/circular_buffer.hpp>
template<class T>
using Alloc = std::pmr::polymorphic_allocator<T>;
using Inner = boost::circular_buffer<int, Alloc<int>>;
using Outer = std::pmr::vector<Inner>;
使用这些别名,Inner
可以与 std::pmr::polymorphic_allocator
一起使用,但不能作为 Outer
.
以下作品:
Outer::allocator_type alloc1; // Allocator type used by Outer to allocate Inner
Inner::allocator_type alloc2; // Allocator type used by Inner to allocate ints
// circular_buffer works if used directly with polymorphic_allocator
Inner inner1; // default arg OK
Inner inner2(alloc1); // pmr with allocator as last argument, also implicitly converts OK
Inner inner3(1, alloc2); // pmr with allocator as last argument OK
// Use to instantiate member functions
inner1.set_capacity(16);
inner2.set_capacity(16);
inner3.set_capacity(16);
inner1.push_back(1);
inner2.push_back(1);
inner3.push_back(1);
但是当用作作用域分配器时(std::pmr::polymorphic_allocator
支持 without any need for std::scoped_allocator_adapter
) it fails to compile with difficult to interpret errors。
其中一个错误是 static_assertion
失败,因为 circular_buffer
无法使用提供的分配器构造,我正在复制(可能不正确)但没有在此处触发断言:
Outer v;
/* Statically asserts because Inner is not constructible
c++/12.0.0/bits/uses_allocator.h:98:60:error: static assertion failed: construction with an allocator must be possible if uses_allocator is true
98 | is_constructible<_Tp, _Args..., const _Alloc&>>::value,
[with
_Args = {};
_Tp = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >;
_Alloc = std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > >;
std::vector<_Tp, _Alloc>::reference = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >&]
*/
// Note: Adding prefix `A` to make names allowed
using A_Tp = boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >;
using A_Alloc = std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > >;
static_assert(std::is_constructible<Inner, const A_Alloc&>::value); // OK
static_assert(std::is_same_v<Inner, A_Tp>); // OK
static_assert(std::is_same_v<typename Outer::allocator_type, A_Alloc>); // OK
v.emplace_back(); // ERROR
v.emplace_back(1); // ERROR
编译器浏览器link
https://godbolt.org/z/4n1Gjhqxh
问题
- 我在这里使用
std::pmr::polymorphic_allocator
不正确吗? - 编译器试图通过错误告诉我什么?
- 为什么从
emplace_back
使用时复制的断言没有失败? std::pmr::polymorphic_allocator
是否引入了任何使其与boost::circular_buffer
不兼容的 new/additional 分配器要求,或者这是boost::circular_buffer
的问题?
编辑
- 在 STL 模板参数的复制中添加了前缀
A
。
第一条错误消息指出这无效:
std::pmr::polymorphic_allocator<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > > alice;
boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> > bob(
std::declval<boost::circular_buffer<int, std::pmr::polymorphic_allocator<int> >>(),
alice
);
它似乎在尝试复制循环缓冲区,同时将分配器作为第二个参数传入。
circular_buffer
的重载不接受这两个参数。
static_assert(std::is_constructible_v< Inner, Inner, Alloc<int>& >);
这基本上就是失败的断言。
作用域分配器协议要求该类型的每个构造函数都有一个相应的分配器扩展版本(通过将分配器参数附加到参数列表,或者通过在前面加上两个参数- allocator_arg_t
后跟分配器)。
这包括复制和移动构造函数,boost::circular_buffer
似乎没有为其提供分配器扩展版本。对这两个分配器扩展的构造函数的要求特别在 C++11 分配器感知容器要求中。
特别是对于 vector
,emplace_back
需要能够在重新分配时复制或移动现有元素,这就是为什么它需要分配器扩展的 copy/move 构造函数。