Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In addition to Mark Ransom's <a href="https://stackoverflow.com/a/11002783/981959">answer</a>, a <code>unique_ptr&lt;X, D&gt;</code> might not even store an <code>X*</code>.</p> <p>If the deleter defines the type <code>D::pointer</code> then that's what is stored, and that might not be a real pointer, it only needs to meet the <code>NullablePointer</code> requirements and (if <code>unique_ptr&lt;X,D&gt;::get()</code> is called) have an <code>operator*</code> that returns <code>X&amp;</code>, but it isn't required to support casting to other types.</p> <p><code>unique_ptr</code> is quite flexible and doesn't necessarily behave very much like a built-in pointer type.</p> <p>As requested, here is an example where the stored type is not a pointer, and therefore casting is not possible. It's a bit contrived, but wraps a made-up database API (defined as a C-style API) in a C++ RAII-style API. The OpaqueDbHandle type meets the <code>NullablePointer</code> requirements, but only stores an integer, which is used as a key to lookup the actual DB connection via some implementation-defined mapping. I'm not showing this as an example of great design, just as an example of using <code>unique_ptr</code> to manage a non-copyable, movable resource which is not a dynamically-allocated pointer, where the "deleter" doesn't just call a destructor and deallocate memory when the <code>unique_ptr</code> goes out of scope.</p> <pre><code>#include &lt;memory&gt; // native database API extern "C" { struct Db; int db_query(Db*, const char*); Db* db_connect(); void db_disconnect(Db*); } // wrapper API class OpaqueDbHandle { public: explicit OpaqueDbHandle(int id) : id(id) { } OpaqueDbHandle(std::nullptr_t) { } OpaqueDbHandle() = default; OpaqueDbHandle(const OpaqueDbHandle&amp;) = default; OpaqueDbHandle&amp; operator=(const OpaqueDbHandle&amp;) = default; OpaqueDbHandle&amp; operator=(std::nullptr_t) { id = -1; return *this; } Db&amp; operator*() const; explicit operator bool() const { return id &gt; 0; } friend bool operator==(const OpaqueDbHandle&amp; l, const OpaqueDbHandle&amp; r) { return l.id == r.id; } private: friend class DbDeleter; int id = -1; }; inline bool operator!=(const OpaqueDbHandle&amp; l, const OpaqueDbHandle&amp; r) { return !(l == r); } struct DbDeleter { typedef OpaqueDbHandle pointer; void operator()(pointer p) const; }; typedef std::unique_ptr&lt;Db, DbDeleter&gt; safe_db_handle; safe_db_handle safe_connect(); int main() { auto db_handle = safe_connect(); (void) db_query(&amp;*db_handle, "SHOW TABLES"); } // defined in some shared library namespace { std::map&lt;int, Db*&gt; connections; // all active DB connections std::list&lt;int&gt; unused_connections; // currently unused ones int next_id = 0; const unsigned cache_unused_threshold = 10; } Db&amp; OpaqueDbHandle::operator*() const { return connections[id]; } safe_db_handle safe_connect() { int id; if (!unused_connections.empty()) { id = unused_connections.back(); unused_connections.pop_back(); } else { id = next_id++; connections[id] = db_connect(); } return safe_db_handle( OpaqueDbHandle(id) ); } void DbDeleter::operator()(DbDeleter::pointer p) const { if (unused_connections.size() &gt;= cache_unused_threshold) { db_disconnect(&amp;*p); connections.erase(p.id); } else unused_connections.push_back(p.id); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload