<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1289: Generic casting requirements for smart pointers</title>
<meta property="og:title" content="Issue 1289: Generic casting requirements for smart pointers">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1289.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#NAD">NAD</a> status.</em></p>
<h3 id="1289"><a href="lwg-closed.html#1289">1289</a>. Generic casting requirements for smart pointers</h3>
<p><b>Section:</b> 22.2 <a href="https://wg21.link/utility">[utility]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Ion Gazta&ntilde;aga <b>Opened:</b> 2009-12-14 <b>Last modified:</b> 2019-02-26</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#utility">issues</a> in [utility].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
In section 16.4.4.6 <a href="https://wg21.link/allocator.requirements">[allocator.requirements]</a>, Table 40 &mdash; Allocator requirements,
the following expression is required for allocator pointers:
</p>

<blockquote>
<table border="1">
<caption>Table 40 &mdash; Allocator requirements</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion/note<br/>pre-/post-condition</th>
<th>Default</th>
</tr>
<tr>
<td><code>static_cast&lt;X::pointer&gt;(w)</code></td>
<td><code>X::pointer</code></td>
<td><code>static_cast&lt;X::pointer&gt;(w) == p</code></td>
<td>&nbsp;</td>
</tr>
</table>
</blockquote>

<p>
To achieve this expression, a smart pointer writer must introduce an explicit
conversion operator from <code>smart_ptr&lt;void&gt;</code> to
<code>smart_ptr&lt;T&gt;</code> so that
<code>static_cast&lt;pointer&gt;(void_ptr)</code> is a valid expression.
Unfortunately this explicit conversion weakens the safety of a smart pointer
since the following expression (invalid for raw pointers) would become valid:
</p>

<blockquote><pre>
smart_ptr&lt;void&gt; smart_v = ...;
smart_ptr&lt;T&gt; smart_t(smart_v);
</pre></blockquote>

<p>
On the other hand, <code>shared_ptr</code> also defines its own casting functions in
20.3.2.2.10 <a href="https://wg21.link/util.smartptr.shared.cast">[util.smartptr.shared.cast]</a>, and although it's unlikely that a
programmer will use <code>shared_ptr</code> as <code>allocator::pointer</code>, having
two different ways to do the same cast operation does not seem reasonable. A
possible solution would be to replace <code>static_cast&lt;X::pointer&gt;(w)</code>
expression with a user customizable (via ADL)
<code>static_pointer_cast&lt;value_type&gt;(w)</code>, and establish the
<code>xxx_pointer_cast</code> functions introduced by <code>shared_ptr</code> as the
recommended generic casting utilities of the standard.
</p>

<p>
Unfortunately, we've experienced problems in Boost when trying to establish
<code>xxx_pointer_cast</code> as customization points for generic libraries (<a
href="http://objectmix.com/c/40424-adl-lookup-explicit-template-parameters.html"
>http://objectmix.com/c/40424-adl-lookup-explicit-template-parameters.html</a>)
because these casting functions are called with explicit template parameters and
the standard says in 13.10.2 <a href="https://wg21.link/temp.arg.explicit">[temp.arg.explicit]</a> p.8 "Explicit template
argument specification":
</p>

<blockquote><p>
8 ...But when a function template with explicit template arguments is used, the
call does not have the correct syntactic form unless there is a function
template with that name visible at the point of the call. If no such name is
visible, the call is not syntactically well-formed and argument-dependent lookup
does not apply.
</p></blockquote>

<p>
So we can do this:
</p>

<blockquote><pre>
template&lt;class BasePtr&gt;
void generic_ptr_swap(BasePtr p)
{
  //ADL customization point
  swap(p, p);
  //...
}
</pre></blockquote>

<p>
but not the following:
</p>

<blockquote><pre>
template&lt;class BasePtr&gt;
void generic_ptr_algo(BasePtr p)
{
  typedef std::pointer_traits&lt;BasePtr&gt;::template
     rebind&lt;Derived&gt; DerivedPtr;
  DerivedPtr dp = static_pointer_cast&lt;Derived&gt;(p);
}
</pre></blockquote>

<p>
The solution to make <code>static_pointer_cast</code> a customization point is to
add a generic declaration (no definition) of <code>static_pointer_cast</code> in a
namespace (like <code>std</code>) and apply "<code>using
std::static_pointer_cast</code>" declaration to activate ADL:
</p>

<blockquote><pre>
namespace std{

template&lt;typename U, typename T&gt;
<i>unspecified</i>
static_pointer_cast(T&amp;&amp;) = delete;

}

template&lt;class BasePtr&gt;
void generic_ptr_algo(BasePtr p)
{
  typedef std::pointer_traits&lt;BasePtr&gt;::template
     rebind&lt;Derived&gt; DerivedPtr;

  //ADL applies because static_pointer_cast is made
  //  visible according to [temp.arg.explicit]/8
  using std::static_pointer_cast;

  DerivedPtr dp = static_pointer_cast&lt;Derived&gt;(p);

  //...
}
</pre></blockquote>

<p>
A complete solution will need also the definition of
<code>static_pointer_cast</code> for raw pointers, and this definition has been
present in Boost (<a
href="http://www.boost.org/boost/pointer_cast.hpp">http://www.boost.org/boost/
pointer_cast.hpp</a>) for years.
</p>

<p><i>[
2010-03-26 Daniel made editorial adjustments to the proposed wording.
]</i></p>


<p><i>[
Moved to NAD Future at 2010-11 Batavia
]</i></p>

<blockquote><p>
This is a new feature rather than a defect. 
It can be added later: "this is such a hairy area that people will put up with changes"
</p></blockquote>

<p><i>[LEWG Kona 2017]</i></p>

<p>Recommend NAD: NAD. Should bring a paper as a proposal for 2020.</p>


<p id="res-1289"><b>Proposed resolution:</b></p>
<p>
Add to section 22.2 <a href="https://wg21.link/utility">[utility]</a> Utility components, Header
<code>&lt;utility&gt;</code> synopsis:
</p>

<blockquote><pre>
// 20.3.X, generic pointer cast functions

template&lt;typename U, typename T&gt;
<i>unspecified</i>
static_pointer_cast(T&amp;&amp;) = delete;

template&lt;typename U, typename T&gt;
<i>unspecified</i>
dynamic_pointer_cast(T&amp;&amp;) = delete;

template&lt;typename U, typename T&gt;
<i>unspecified</i>
const_pointer_cast(T&amp;&amp;) = delete;

//Overloads for raw pointers
template&lt;typename U, typename T&gt;
auto static_pointer_cast(T* t) -&gt; decltype(static_cast&lt;U*&gt;(t));

template&lt;typename U, typename T&gt;
auto dynamic_pointer_cast(T* t) -&gt; decltype(dynamic_cast&lt;U*&gt;(t));

template&lt;typename U, typename T&gt;
auto const_pointer_cast(T* t) -&gt; decltype(const_cast&lt;U*&gt;(t));
</pre></blockquote>

<p>
Add to section 22.2 <a href="https://wg21.link/utility">[utility]</a> Utility components, a new subclause
20.3.X Pointer cast utilities [pointer.cast]:
</p>

<blockquote>
<p>
20.3.X Pointer cast utilities [pointer.cast]
</p>

<p>
1 The library defines generic pointer casting function templates so that template code
can explicitly make these names visible and activate argument-dependent lookup
for pointer cast calls.
</p>

<pre>
//Generic declarations
template&lt;typename U, typename T&gt;
<i>unspecified</i>
static_pointer_cast(T&amp;&amp;) = delete;

template&lt;typename U, typename T&gt;
<i>unspecified</i>
dynamic_pointer_cast(T&amp;&amp;) = delete;

template&lt;typename U, typename T&gt;
<i>unspecified</i>
const_pointer_cast(T&amp;&amp;) = delete;
</pre>

<p>
2 The library also defines overloads of these functions for raw pointers.
</p>

<pre>
//Overloads for raw pointers
template&lt;typename U, typename T&gt;
auto static_pointer_cast(T* t) -&gt; decltype(static_cast&lt;U*&gt;(t));
</pre>

<blockquote><p>
<i>Returns:</i> <code>static_cast&lt;U*&gt;(t)</code>
</p></blockquote>

<pre>
template&lt;typename U, typename T&gt;
auto dynamic_pointer_cast(T* t) -&gt; decltype(dynamic_cast&lt;U*&gt;(t));
</pre>

<blockquote><p>
<i>Returns:</i> <code>dynamic_cast&lt;U*&gt;(t)</code>
</p></blockquote>

<pre>
template&lt;typename U, typename T&gt;
auto const_pointer_cast(T* t) -&gt; decltype(const_cast&lt;U*&gt;(t));
</pre>

<blockquote><p>
<i>Returns:</i> <code>const_cast&lt;U*&gt;(t)</code>
</p></blockquote>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
#include &lt;utility&gt; //static_pointer_cast
#include &lt;memory&gt;  //pointer_traits

class Base{};
class Derived : public Base{};

template&lt;class BasePtr&gt;
void generic_pointer_code(BasePtr b)
{
   typedef std::pointer_traits&lt;BasePtr&gt;::template
      rebind&lt;Derived&gt; DerivedPtr;

   using std::static_pointer_cast;
   //ADL applies now that static_pointer_cast is visible
   DerivedPtr d = static_pointer_cast&lt;Derived&gt;(b);
}
</pre></blockquote>

<p>
&mdash; <i>end example</i>]
</p>

</blockquote>

<p>
Replace in section 16.4.4.6 <a href="https://wg21.link/allocator.requirements">[allocator.requirements]</a> Table 40 &mdash; Allocator
requirements, the following table entries for allocator pointers:
</p>

<blockquote>
<table border="1">
<caption>Table 40 &mdash; Allocator requirements</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion/note<br/>pre-/post-condition</th>
<th>Default</th>
</tr>

<tr>
<td><code>static<ins>_pointer</ins>_cast&lt;<del>X::pointer</del><ins>T</ins>&gt;(w)</code></td>
<td><code>X::pointer</code></td>
<td><code>static<ins>_pointer</ins>_cast&lt;<del>X::pointer</del><ins>T</ins>&gt;(w) == p</code></td>
<td>&nbsp;</td>
</tr>

<tr>
<td><code>static<ins>_pointer</ins>_cast&lt;<del>X::const_pointer</del><ins>const T</ins>&gt;(w)</code></td>
<td><code>X::const_pointer</code></td>
<td><code>static<ins>_pointer</ins>_cast&lt;<del>X::const_pointer</del><ins>const T</ins>&gt;(z) == q</code></td>
<td>&nbsp;</td>
</tr>

</table>
</blockquote>






</body>
</html>
