Bru*_*ams 7 c++ templates allocator fancy-pointers
我正在尝试实现一个分配器,它允许我使用带有 STL 类型的boost::interprocess::offset_ptr的“花哨”指针。
\n作为一个独立的模板,指针本身工作得很好,但我很难让它与std::vector或boost::containers::vector
我为指针实现的事情列表是:
\ntemplate<class T>\nclass OffsetPtr ...\nRun Code Online (Sandbox Code Playgroud)\n分配器实现
\n但仍然缺少一些东西,可能是好几样东西。
\n我需要OffsetPtr<void>和的模板专业化吗OffsetPtr<const void>?
到目前为止,没有错误消息表明这一点,但我知道需要 rebind(),以便我们可以拥有基于 void* 的 STL 容器实现。
\n还:
\n这与我的另一个问题有关
\n我的另一个问题是如何验证我实际上已经实现了一个概念(pre c++20)的特征,这在理论上是一个普遍问题。
\n另请参阅使用花式指针实现自定义分配器
\n我有两个具体问题,到目前为止我无法找到。\n一个与 相关move_iterator,另一个与rebind和/或使用void.
这是尝试使用 std::vector 时的错误示例:
\nfrom /foo/bar/OffsetPtrAllocatorTest.cpp:8:\n/usr/include/c++/8/bits/stl_uninitialized.h: In instantiation of _ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = std::move_iter\nator<Memory::OffsetPtr<int, long int> >; _ForwardIterator = Memory::OffsetPtr<int, long int>; _Allocator = Memory::OffsetPtrAllocator<int>]:\n/usr/include/c++/8/bits/stl_vector.h:1401:35: required from std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIter\nator) [with _ForwardIterator = std::move_iterator<Memory::OffsetPtr<int, long int> >; _Tp = int; _Alloc = Memory::OffsetPtrAllocator<int>; std::vector<_Tp, _Alloc>::pointer = Memory::OffsetPtr<int, long int>; st\nd::vector<_Tp, _Alloc>::size_type = long unsigned int]\n/usr/include/c++/8/bits/vector.tcc:74:12: required from void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = int; _Alloc = Memory::OffsetPtrAllocator<int>; std::vector<_Tp, \n_Alloc>::size_type = long unsigned int]\n/foo/bar/OffsetPtrAllocatorTest.cpp:46:16: required from here\n/usr/include/c++/8/bits/stl_uninitialized.h:275:25: error: no matching function for call to __gnu_cxx::__alloc_traits<Memory::OffsetPtrAllocator<int>, int>::construct(Memory::OffsetPtrAllocator<int>&, int*, std\n::move_iterator<Memory::OffsetPtr<int, long int> >::reference)\n __traits::construct(__alloc, std::__addressof(*__cur), *__first);\n ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nIn file included from /usr/include/c++/8/bits/stl_construct.h:61,\n from /usr/include/c++/8/deque:62,\n from /usr/include/cppunit/Message.h:11,\n from /usr/include/cppunit/Exception.h:5,\n from /usr/include/cppunit/TestCaller.h:4,\n from /usr/include/cppunit/extensions/HelperMacros.h:9,\n from /foo/bar/OffsetPtrAllocatorTest.cpp:8:\n/usr/include/c++/8/ext/alloc_traits.h:82:7: note: candidate: template<class _Ptr, class ... _Args> static typename std::enable_if<std::__and_<std::is_same<typename std::allocator_traits<_Alloc>::pointer, _Ptr>,\n std::__not_<std::is_pointer<_Ptr> > >::value>::type __gnu_cxx::__alloc_traits<_Alloc, <template-parameter-1-2> >::construct(_Alloc&, _Ptr, _Args&& ...) [with _Ptr = _Ptr; _Args = {_Args ...}; _Alloc = Memory::OffsetPtrAllocator<int>; <template-parameter-1-2> = int]\n construct(_Alloc& __a, _Ptr __p, _Args&&... __args)\n ^~~~~~~~~\n/usr/include/c++/8/ext/alloc_traits.h:82:7: note: template argument deduction/substitution failed:\nRun Code Online (Sandbox Code Playgroud)\n尝试使用 boost::container::vector 时出现不同的错误:
\n尝试 boost 的原因是,某些 STL 实现存在错误,这意味着如果不进行额外修改,它们就无法按预期工作。\n我希望暴露我的实现中的不同缺陷,以帮助理解问题所在。
\n刚刚回到这里,我现在意识到我的 OffsetPtr 类确实可以在 RHEL8 上的 gcc 4.8 上使用分配器,但不能在 Ubuntu 上的 gcc 9.4.0 上使用,因此错误是由两个版本之间的一些差异引起的。
\n再次回到这一点。我创建了一个完整的自包含示例,但无法在 gcc 9.4.0 (Ubuntu 20) 上编译。这个在 4.8 (RHEL8) 上也失败了,尽管我觉得通过向分配器添加 Construction() 模板,我比以前更接近了。
\n我在这种情况下得到的错误是:
\nIn file included from /usr/include/c++/8/bits/stl_algobase.h:67,\n from /usr/include/c++/8/vector:60,\n from /home/brucea/scrap/offsetptr2/main.cpp:2:\n/usr/include/c++/8/bits/stl_iterator.h: In instantiation of \xe2\x80\x98std::move_iterator<_Iterator>::reference std::move_iterator<_Iterator>::operator*() const [with _Iterator = OffsetPtr<int, long int>; std::move_iterator<_Iterator>::reference = int&&]\xe2\x80\x99:\n/usr/include/c++/8/bits/stl_uninitialized.h:275:61: required from \xe2\x80\x98_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = std::move_iterator<OffsetPtr<int, long int> >; _ForwardIterator = OffsetPtr<int, long int>; _Allocator = OffsetPtrAllocator<int>]\xe2\x80\x99\n/usr/include/c++/8/bits/stl_vector.h:1401:35: required from \xe2\x80\x98std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator<OffsetPtr<int, long int> >; _Tp = int; _Alloc = OffsetPtrAllocator<int>; std::vector<_Tp, _Alloc>::pointer = OffsetPtr<int, long int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]\xe2\x80\x99\n/usr/include/c++/8/bits/vector.tcc:74:12: required from \xe2\x80\x98void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = int; _Alloc = OffsetPtrAllocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]\xe2\x80\x99\n/home/brucea/scrap/offsetptr2/main.cpp:743:16: required from here\n/usr/include/c++/8/bits/stl_iterator.h:1047:16: error: invalid static_cast from type \xe2\x80\x98const int\xe2\x80\x99 to type \xe2\x80\x98std::move_iterator<OffsetPtr<int, long int> >::reference\xe2\x80\x99 {aka \xe2\x80\x98int&&\xe2\x80\x99}\n { return static_cast<reference>(*_M_current); }\n ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n/usr/include/c++/8/bits/ptr_traits.h: In instantiation of \xe2\x80\x98constexpr typename std::pointer_traits<_Ptr>::element_type* std::__to_address(const _Ptr&) [with _Ptr = OffsetPtr<int, long int>; typename std::pointer_traits<_Ptr>::element_type = int]\xe2\x80\x99:\n/usr/include/c++/8/ext/alloc_traits.h:84:46: required from \xe2\x80\x98static typename std::enable_if<std::__and_<std::is_same<typename std::allocator_traits<_Alloc>::pointer, _Ptr>, std::__not_<std::is_pointer<_Ptr> > >::value>::type __gnu_cxx::__alloc_traits<_Alloc, <template-parameter-1-2> >::construct(_Alloc&, _Ptr, _Args&& ...) [with _Ptr = OffsetPtr<int, long int>; _Args = {int}; _Alloc = OffsetPtrAllocator<int>; <template-parameter-1-2> = int; typename std::enable_if<std::__and_<std::is_same<typename std::allocator_traits<_Alloc>::pointer, _Ptr>, std::__not_<std::is_pointer<_Ptr> > >::value>::type = void]\xe2\x80\x99\n/usr/include/c++/8/bits/vector.tcc:103:30: required from \xe2\x80\x98void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = int; _Alloc = OffsetPtrAllocator<int>]\xe2\x80\x99\n/usr/include/c++/8/bits/stl_vector.h:1091:9: required from \xe2\x80\x98void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = int; _Alloc = OffsetPtrAllocator<int>; std::vector<_Tp, _Alloc>::value_type = int]\xe2\x80\x99\n/home/brucea/scrap/offsetptr2/main.cpp:744:18: required from here\n/usr/include/c++/8/bits/ptr_traits.h:165:31: error: invalid conversion from \xe2\x80\x98const int*\xe2\x80\x99 to \xe2\x80\x98std::pointer_traits<OffsetPtr<int, long int> >::element_type*\xe2\x80\x99 {aka \xe2\x80\x98int*\xe2\x80\x99} [-fpermissive]\n { return std::__to_address(__ptr.operator->()); }\n ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~\nRun Code Online (Sandbox Code Playgroud)\n
\n\nDo I need template [specializations] for
\nOffsetPtr<void>andOffsetPtr<const void>
\xc2\xa716.4.4.6.2 Allocator Completeness Requirements states:
\n\n\n如果
\nX是 类型 的分配器类T,X则还满足\n分配器完整性要求(无论是否T是完整类型):\n
\n- (1.1)\n
\nXis a complete type, and- \n
allocator_\xc2\xadtraits<X>(1.2)\n除以下之外的所有成员类型value_\xc2\xadtypeare complete types.
是的,您需要专门化(如果OffsetPtrAllocator<void>表示为X X::pointer,则这是必需的OffsetPtr<void>,因为按照规定,它需要是完整类型[通过allocator_traits<X>::pointer]),因为void&(对“void”的引用)是无效的,因为void它是一个不完整类型,不能完成(参见:\xc2\xa76.8.2.14 基本类型).
\n\n我真的需要实现移动语义吗?
\n
据我了解:您的分配器需要一个移动构造函数才能符合标准。(参见:\xc2\xa716.4.4.6 Cpp17Allocator 要求)
\nlet T, U: cv 不合格的对象类型。
\nlet X: Allocator<T>
\nlet Y: Allocator<U>
\nlet a: 类型的左值X
\nlet b: 类型的左值Y
X u(std::move(a));\nX u = std::move(a);\n// Postconditions: The value of a is unchanged and is equal to u.\n// Throws: Nothing.\nX u(std::move(b));\n// Postconditions: u is equal to the prior value of X(b).\n// Throws: Nothing.\nRun Code Online (Sandbox Code Playgroud)\n对于模板实例化错误:在template <class T> struct OffsetPtr成员函数中返回T&将无效T = void由于上述原因,
希望这可以帮助。
\n