gpt4 book ai didi

c++ - GCC 4.7 中是否存在错误。 2's implementation of shared_ptr' s(模板化)赋值运算符?

转载 作者:IT老高 更新时间:2023-10-28 22:25:52 30 4
gpt4 key购买 nike

我的问题涉及 shared_ptr 的赋值运算符模板在 GCC 4.7.2 中的实现,我怀疑它包含一个错误。

前提 1:C++11 标准

这里是我说的赋值运算符模板的签名:

template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;

来自 C++11 标准 (20.7.2.2.3):

“等价于 shared_ptr(r).swap(*this)。”

换句话说,赋值运算符模板是根据构造函数模板定义的。构造函数模板的签名如下:

template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;

来自 C++11 标准 (20.7.2.2.1):

“要求:除非 Y* 可隐式转换为 T*,否则 [...] 构造函数不得参与重载决议。”

前提 2:GCC 4.7.2 的实现:

现在 GCC 4.7.2 的构造函数模板的实现对我来说似乎是正确的(std::__shared_ptrstd::shared_ptr 的基类):

template<typename _Tp1, typename = 
typename std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
:
_M_ptr(__r._M_ptr),
_M_refcount()
{
_M_refcount._M_swap(__r._M_refcount);
__r._M_ptr = 0;
}

但是,GCC 4.7.2 对赋值运算符模板的实现如下:

template<typename _Tp1>
__shared_ptr& operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
return *this;
}

让我印象深刻的是,这个操作不是根据构造函数模板定义的,也不是swap()定义的。特别是,普通赋值 _M_ptr = __r._M_ptr 不会产生与显式检查类型 _Tp1*_Tp* 相同的结果通过 std::is_convertible 进行转换(可以专门化)。

前提 3:VC10 实现

我注意到 VC10 在这方面确实有一个更符合标准的实现,我认为这是正确的,并且在我的测试用例中表现得如我所料(而 GCC 没有):

template<class _Ty2>
_Myt& operator=(const shared_ptr<_Ty2>& _Right)
{
// assign shared ownership of resource owned by _Right
shared_ptr(_Right).swap(*this);
return (*this);
}

问题:

GCC 4.7.2 的 shared_ptr 实现中是否确实存在错误?我找不到任何关于这个问题的错误报告。

发布脚本:

如果你想问我我的测试用例是什么,为什么我会关心这个看似不重要的细节,为什么我似乎暗示我需要专门化 std::is_convertible ,请在聊天中这样做。这是一个很长的故事,没有办法在不被误解的情况下总结它(及其所有令人不快的后果)。提前谢谢你。

最佳答案

What strikes me is that this operation is not defined in terms of the constructor template, nor of swap().

它不需要,它只需要表现得就好像它是在那些条款中定义的那样。

In particular, the plain assignment _M_ptr = __r._M_ptr does not yield the same result as when the types _Tp1* and _Tp* are explicitly checked for convertibility through std::is_convertible (which can be specialized).

我不同意:[meta.type.synop]/1 除非另有说明,否则为本子条款中定义的任何类模板添加特化的程序的行为是未定义的。

所以你不能改变is_convertible<Y*, T*>的意思如果 Y*可转换为 T*那么分配将起作用,因为(指针和引用计数对象的)两个分配都是 noexcept最终结果等同于交换。如果指针不可转换,则赋值将无法编译,但 shared_ptr(r).swap(*this) 也会编译失败。 ,所以还是等价的。

如果我错了,请提交错误报告,我会修复它,但我认为符合标准的程序无法检测 libstdc++ 实现与标准要求之间的差异。也就是说,我不会反对将其更改为以 swap 的形式实现。 .当前的实现直接来自 shared_ptrBoost 1.32 , 我不知道 Boost 是否仍然以相同的方式执行此操作,或者它是否使用 shared_ptr(r).swap(*this)现在。

[全面披露,我是一名 libstdc++ 维护者,主要负责 shared_ptr代码,最初由 boost::shared_ptr 的作者慷慨捐赠从此被我残害。]

关于c++ - GCC 4.7 中是否存在错误。 2's implementation of shared_ptr' s(模板化)赋值运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14221524/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com