在GCC 4.7.2中破坏了std :: unique_ptr

时间:2012-12-28 02:08:34

标签: c++ c++11 unique-ptr

我正在尝试使用std::unique_ptr来将整数句柄存储到某些不透明对象中。为此,我定义了一个自定义删除器类型,它执行typedef int pointer以将原始指针类型覆盖为int而不是int*。此过程在本网站的最后一节中进行了描述:http://asawicki.info/news_1494_unique_ptr_in_visual_c_2010.html

以下是一些示例代码,可以更好地说明我正在尝试做的事情:

#include <memory>
#include <iostream>

static void close(int p)
{
    std::cout << p << " has been deleted!" << std::endl;
}

struct handle_deleter
{
    typedef int pointer;
    void operator()(pointer p) { close(p); }
};

typedef std::unique_ptr< int, handle_deleter> unique_handle;

int main(int argc, char *argv[])
{
    unique_handle handle(1);

    return 0;
}

当我使用GCC 4.7.2编译此代码时,出现以下错误:

In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/memory:86:0,
                 from unique_ptr_test.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/unique_ptr.h: In instantiation of ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = int; _Dp = handle_deleter]’:
unique_ptr_test.cpp:19:23:   required from here
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/unique_ptr.h:172:2: error: invalid operands of types ‘int’ and ‘std::nullptr_t’ to binary ‘operator!=’

~unique_ptr程序的代码如下:

// Destructor.
~unique_ptr() noexcept
{
    auto& __ptr = std::get<0>(_M_t);
    if (__ptr != nullptr)
      get_deleter()(__ptr);
    __ptr = pointer();
}

根据我的说法,对nullptr的检查没有意义,因为原始指针类型是int(而不是int*,因为它覆盖了HandleDeleter)。奇怪的是,此代码在GCC 4.6.1下编译时没有错误。执行时,示例显示“1已被删除!”如预期的那样。

我想知道是否有任何细节我忽略或者它是否真的是GCC的独立资产的STL实施中的一个错误。

谢谢,

PMJ

1 个答案:

答案 0 :(得分:7)

正如我在评论中所说,如果您传递的删除类型具有嵌套的pointer typedef,则它必须满足 NullablePointer 要求:

20.7.1.2 [unique.ptr.single] p3

  

如果类型remove_reference<D>::type::pointer存在,则unique_ptr<T, D>::pointer应为remove_reference<D>::type::pointer的同义词。否则unique_ptr<T, D>::pointer应为T*的同义词。 unique_ptr<T, D>::pointer类型应满足NullablePointer(17.6.3.3)的要求。

然后§17.6.3.3列出类型必须满足的所有要求才能成为NullablePointer。某些语义列在表中,其中:

  

u表示标识符,t表示类型P的非常量左值,ab表示类型的值(可能const 1}})Pnp表示类型的值(可能是conststd::nullptr_t

Expression    Return type                         Operational semantics
P u(np);                                          post: u == nullptr
P u = np;
P(np)                                             post: P(np) == nullptr
t = np        P&                                  post: t == nullptr
a != b        contextually convertible to bool    !(a == b)
a == np       contextually convertible to bool    a == P()
np == a
a != np       contextually convertible to bool    !(a == np)
np != a

现在,最简单的解决方案是将int包装在提供这些语义的类型中:

#include <cstddef> // std::nullptr_t

struct handle{
  handle() : value(0){}
  handle(std::nullptr_t) : value(0){}
  /*explicit*/ handle(int v) : value(v){} // make it explicit if you need it
  // special members can be generated

  handle& operator=(std::nullptr_t){ value = 0; return *this; }

  // contextual conversion to bool
  explicit operator bool() const{ return value != 0; }

  int value;
};

bool operator==(handle lhs, handle rhs){ return lhs.value == rhs.value; }
bool operator!=(handle lhs, handle rhs){ return lhs.value != rhs.value; }
// comparision against 'nullptr' is handled by the above operators
// since 'nullptr' can be implicitly converted to 'handle'