1

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();
}

int私によると、生のポインタ型は(でint*オーバーライドするためではなく)であるため、nullptrに対するチェックは意味がありませんHandleDeleter。不思議なことに、このコードはGCC4.6.1でエラーなしでコンパイルされます。実行すると、サンプルには「1が削除されました!」と表示されます。予想通り。

私が見落としている詳細があるのか​​、それともGCCのunique_ptrのSTL実装内のバグなのか疑問に思いました。

ありがとう、

PMJ

4

1 に答える 1

7

コメントで述べたように、渡すデリータ型にネストされたpointertypedef がある場合は、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*ます。型は(17.6.3.3)unique_ptr<T, D>::pointerの要件を満たさなければなりNullablePointerません。

次に、§17.6.3.3型が NullablePointer になるために満たす必要があるすべての要件をリストします。特定のセマンティクスが表にリストされています。

uは識別子を表し、 typeのt非 const 左辺値を表し、 type (おそらく)の値を表し、 type (おそらく)の値を表します。PabconstPnpconststd::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'
于 2012-12-28T10:05:22.723 に答える