- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我尝试创建一个使用智能指针的自定义内存分配器。我没有发布代码,因为它太大并且没有添加太多信息。然后我用 std::vector
对其进行了测试.它在 Xcode 上运行良好。但是当我尝试在 Visual Studio 12 (2013) 中构建相同的代码时,构建失败并出现以下错误:
...vector(873): error C2660: '
std::_Wrap_alloc< my_allocator< int > >::construct
' : function does not take 2 arguments
问题出在 push_back 方法中:
void push_back(value_type&& _Val)
{
....
this->_Getal().construct(this->_Mylast,
_STD forward<value_type>(this->_Myfirst[_Idx]));
....
}
错误信息有点困惑。真正的问题是 this->_Mylast
是 my_allocator< int >::pointer
类型,这是一个智能指针,构造方法需要 int*
.
所以,问题很简单:自定义内存分配器中使用的指针类型有什么要求?应该 X::pointer
可转换为原始指针?如果是,那它们就毫无用处了。
实际上我希望那行代码看起来像:
this->_Getal().construct(addressof(*(this->_Mylast)),
_STD forward<value_type>(this->_Myfirst[_Idx]));
让我们尝试在 C++ 标准中找到答案,它说:
[17.6.3.5-5] An allocator type X shall satisfy the requirements of CopyConstructible (17.6.3.1). The
X::pointer
,X::const_pointer
,X::void_pointer
, andX::const_void_pointer
types shall satisfy the requirements of NullablePointer (17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception.X::pointer
andX::const_pointer
shall also satisfy the requirements for a random access iterator (24.2)
如果我们看一下 NullablePointer reqs,它们会添加一些其他要求:
[17.6.3.3] A NullablePointer type is a pointer-like type that supports null values. A type P meets the requirements of NullablePointer if:
(1.1) — P satisfies the requirements of EqualityComparable, DefaultConstructible, CopyConstructible, CopyAssignable, and Destructible...
如果我检查随机访问迭代器要求,我也没有发现任何明确提及其转换为原始指针的内容。但在少数地方使用 addressof
的方法使用(例如 24.2.1-5)。
此外,它不是 Microsoft 的 std::vector
中唯一的地方。实现地点X::pointer
和原始指针被假定为相等。我想知道,我错过了什么?
编辑:我将在此处添加一段 my_allocator 定义:
class my_allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef my_ptr<T> pointer;
typedef my_ptr<const T> const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef my_ptr<void> void_pointer;
typedef my_ptr<const void> const_void_pointer;
<constructors>
pointer allocate(size_type n, const_void_pointer = nullptr);
void deallocate(const pointer& ptr, size_type elements_num);
};
最佳答案
为了解决这个问题,我创建了一个 to_raw_pointer
函数,它恰好适用于任何实现 operator->()
的“花式指针”。您可以在 libc++ implementation 中找到它.
这里是:
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_Tp*
__to_raw_pointer(_Tp* __p) _NOEXCEPT
{
return __p;
}
template <class _Pointer>
inline _LIBCPP_INLINE_VISIBILITY
typename pointer_traits<_Pointer>::element_type*
__to_raw_pointer(_Pointer __p) _NOEXCEPT
{
return _VSTD::__to_raw_pointer(__p.operator->());
}
它通过以非常规方式调用 operator->()
来工作。这个操作符必须要么调用另一个operator->()
,要么返回一个真正的指针。实指针的重载用恒等函数打破了递归。所以这会像这样使用:
this->_Getal().construct(__to_raw_pointer(this->_Mylast),
_STD forward<value_type>(this->_Myfirst[_Idx]));
construct
被指定为采用真正的指针,而不是花哨的指针。并且没有指定从花哨指针到实际指针的隐式转换。容器必须使用诸如 to_raw_pointer
或 addressof
之类的东西。
容器还需要通过 allocator_traits
调用 construct
,而不是如图所示直接在存储的分配器上调用它。这是为了允许 construct
被 allocator_traits
“默认”,而不是要求分配器实现 construct
。
目前,operator*()
和 operator->()
通常都要求花哨的指针在调用该运算符之前非空。但是我预计将来 operator->()
的这一要求会放宽。
更新
我写上面的时候有点着急。现在我有时间了,我将包含对 allocator::pointer
类型的完整要求。然而,在重新阅读问题时,我看到 Maxym题主已经做好了,这里不再赘述。
在std中但并不完全明显的一件事是四种指针类型之间的隐式和显式转换:pointer
、const_pointer
、void_pointer
和 const_void_pointer
:
implicit allocator pointer conversions:
+--------------------------------------+
| pointer --> const_pointer |
| | \ | |
| | --------- | |
| \|/ _\| \|/ |
| void_pointer --> const_void_pointer |
+--------------------------------------+
explicit allocator pointer conversions:
+--------------------------------------+
| pointer const_pointer |
| /|\ /|\ |
| | | |
| | | |
| void_pointer const_void_pointer |
+--------------------------------------+
也就是说,你可以从非const
隐式转换为const
,从非void
隐式转换为void
,您可以显式将 void
转换为非void
。但是容器无法从 allocator::const_pointer
或 allocator 中
。一旦容器进入const_cast
(抛弃const
-ness): :const_void_pointerconst
,就再也回不来了。
关于c++ - 具有自定义指针类型的内存分配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27646996/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!