220 31712 <46a85060-631b-49e5-94f3-ab07429d8085@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Matthew Fioravante <fmatthew5876@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Complexities caused by using unique_ptr and move semantics
Date: Thu, 23 Mar 2017 09:38:19 -0700 (PDT)
Lines: 547
Approved: news@gmane.org
Message-ID: <46a85060-631b-49e5-94f3-ab07429d8085@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_184_1227975421.1490287099071"
X-Trace: blaine.gmane.org 1490287108 23623 195.159.176.226 (23 Mar 2017 16:38:28 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Thu, 23 Mar 2017 16:38:28 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDELF54RTIGRB67TZ7DAKGQEX6QB4ZY@isocpp.org Thu Mar 23 17:38:23 2017
Return-path: <std-proposals+bncBDELF54RTIGRB67TZ7DAKGQEX6QB4ZY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-pf0-f198.google.com ([209.85.192.198])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDELF54RTIGRB67TZ7DAKGQEX6QB4ZY@isocpp.org>)
	id 1cr5kd-000584-BE
	for gclcip-std-proposals@m.gmane.org; Thu, 23 Mar 2017 17:38:15 +0100
Original-Received: by mail-pf0-f198.google.com with SMTP id p189sf318541414pfp.5
        for <gclcip-std-proposals@m.gmane.org>; Thu, 23 Mar 2017 09:38:21 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:subject:mime-version:x-original-sender
         :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=uyxFPkQok43dgAwRGBx9kuL1kE8GNFl/jyUmgfqqmJc=;
        b=iffhh6wxFJVEkHFXzKEzYXDb5+w185tx0oaDwiXNaR4PaUZcnCicNJv3BbS9AMJUaY
         txngW/ZaEst0fiS3ksH+UqFTjMgvWTL/QiLLB43C7AkPoy83Y2CfD9YS3XcwJAnc2Jmf
         eTIVGiV8AOnn6Lbrq3w7kX+N/fJhdxtLbahiZIxI6rRDBf1Hpg/EK9WZbEPyMA9YY7+l
         17xJ5pPbk0SMRSGZlaK2URy0xzldFjdo2rVQ8tbv/djEH+z3oFaHwG9VEAscBkcMp065
         kEZ+F82aGAsOL2VLLJiCXzUFpLA/EQ0JWpficE0Sar+3szhS52xYgKmgBiLl7tut1jle
         oupw==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:subject:mime-version:x-original-sender
         :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=uyxFPkQok43dgAwRGBx9kuL1kE8GNFl/jyUmgfqqmJc=;
        b=ZcPrKDj3+DFN/3YuderOL8ddG6grX41D0njNu4WEtkqDoahIeSt646U0VdS0+5YHMp
         oe1SGY2rFxolO8DJW32Vn9lxB1W32S7NkBqi9nrxvL++V4JNj9fKYb9ejwKU5kJk6akD
         x2aYXNZnJ+Gl+ylo+dh9CZg8Y5UkHYWFRW94yv3fFWyxpdxoNE4K2wc2FstK8mY/j7NC
         cYwvfLFxd5RZCrkgqikzH2ZxWXd16KCvYMigw2E52oMgYFvmZST7pXBZBPOp+MXx4uex
         z4GAa63xhZXEtQkiYlQtnMo6Gep3pKdoa966fSSMIdbJiNoAUSz6Vgrho63ZffgzSqxR
         fwww==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=uyxFPkQok43dgAwRGBx9kuL1kE8GNFl/jyUmgfqqmJc=;
        b=Oah/3nTc1eWsdgP9Gw9i7Vtzbr1RA75Detvu9Ff1cRJvisVhly/ulfCaK/0ZbLexFu
         CoNELp1Isk5Lo1oOMzlI8utiC8/ub6vW6DAU8gN+GkN6DSxBRV/dMKsFQtdC93B7HpWW
         OF3kf2+ml3FD/Y2ksmcGypB9+Nyr43O9BiCrz/1Ad8m4eN0cFxdDh9HasNAszQIx18Vb
         VYc5lRvsQLX37VLeU4/4+IVlvPN5lauGoY/mwCD4rk6dYm4gawwFibR7LJf6iFScg8G2
         hbZlPZbntc6FG3cCRwFOMY1eBULPtrCXouT+aes0Vs1jb27kt929EEGPDJER5sJc2TAm
         OVaQ==
X-Gm-Message-State: AFeK/H1g8t1aQIhY17cqO9okqf+LLEPJiDIAh3e/+YMMSnKkvRIbc2mA1BpBQnJc9O5qkA==
X-Received: by 10.99.115.92 with SMTP id d28mr1083942pgn.124.1490287100875;
        Thu, 23 Mar 2017 09:38:20 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.33.91 with SMTP id l27ls529573otd.41.gmail; Thu, 23 Mar
 2017 09:38:19 -0700 (PDT)
X-Received: by 10.157.22.200 with SMTP id s8mr314241ots.16.1490287099713;
        Thu, 23 Mar 2017 09:38:19 -0700 (PDT)
X-Original-Sender: fmatthew5876@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:31712
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/31712>

------=_Part_184_1227975421.1490287099071
Content-Type: multipart/alternative; 
	boundary="----=_Part_185_1235225468.1490287099072"

------=_Part_185_1235225468.1490287099072
Content-Type: text/plain; charset=UTF-8

I don't have a proposal or a real solution. This is more intended to 
highlight some of the problems related to unique ownership and move 
semantics.

1. Its too easy to accidentally use a moved from object by mistake

Consider this code:

void Container::addThing(unique_ptr<Thing> p) {
  this->_things.push_back(std::move(p));
  if(logging_enabled) {
   std::cout << "Added thing " << p->name() << " " << p->foo() << " " << p->
bar() << std::endl;
  }
  return;
}

I've seen this kind of bug many times. Its very easy to write and the 
compiler provides no help to you. Even better since the bug is hidden when 
logging is disabled, it could easily pass into production. Its also 
somewhat of an expert problem when explaining to novices.

Now here's an attempt to fix the bug the right way. But we still have a 
mistake! Again no help from the compiler. Also unless you're really paying 
attention, a quick skim through the code will likely miss this one.

void Container::addThing(unique_ptr<Thing> p) {
  auto* pc = p.get();
  this->_things.push_back(std::move(p));
  if(logging_enabled) {
   std::cout << "Added thing " << pc->name() << " " << pc->foo() << " " << p
->bar() << std::endl;
  }
  return;
}

After we move p into _things, we never need to touch p again. Unfortunately 
in this case and many others, we can't really introduce scopes with {} to 
eliminate p from the local namespace and prevent these kinds of bugs. 

A possible solution here might be some kind of [[discard]] attribute or a 
std::move_final() which is std::move() + [[discard]] together. So that the 
compiler would warn on any use of p after the move. 


2. unique_ptr<T> and T* being different types can cause pessimizations 
because of language rules.

Of course its a good thing that these types are different. One is an owner 
and one is not. Using a different type means we can enlist the help of the 
compiler to enforce correctness.

Sometimes I have a container with keeps a set of unique_ptrs, and I want to 
view that set.

class OwningContainer {
 public:
  array_view<const unique_ptr<Thing>> getThings() const { return _things; }
 private:
  std::vector<unique_ptr<Thing>> _things;
};

class NonOwningContainer {
 public:
  array_view<const Thing*> getThings() const { return _things; }
 private:
  std::vector<Thing*> _things;
};

//Out of line function, maybe lives in a 3rd party library.
void f(array_view<const Thing*> things);

void g(const OwningContainer& c){
  f(c.getThings()); //Compiler Error
}
void h(const NonOwningContainer& c) {
  f(c.getThings()); //Ok
}

The getThings() method of OwningContainer and NonOwningContainer methods 
have the exact same semantics. We're getting a const view of the stored 
thing pointers. The returned objects are even bitwise and machine code 
(after optimization) identical, but are "marked up" by the compiler with 
different types.

From the limited perspective of the code calling getThings(), whether or 
not the container owns the pointers is an implementation detail. The caller 
does not and should not care whether the pointers are stored raw, 
unique_ptr. He just wants to view the collection and do something with it.

The big problem here is that the return types of getThings() are different. 
This means that in a generic context, you need to start introducing 
templates in order to handle all possible pointer types. Adding templates 
complicates the code and slows down compile times.

Also since const unique_ptr<T> and const T* are semantically and even 
bitwise identical, using templates here will unnecessarily bloat your code 
with 2 functions that do the exact same thing. This increases your binary 
size and puts more pressure on the icache.

In this example, we must change f() to be a template. Even though the 
actual compiled down machine code will be identical. The biggest problem I 
have with this example is that the problem comes from artificial language 
rules and not physical limits about how hardware and memory works. That 
goes against the zero overhead principle of C++.

In order to avoid making f() a template here, there are a few options today 
we can try with OwningContainer:
1. Return vector<Thing*> by value, doing a copy and memory allocations at 
every call. (very slow)
2. Store a second vector<Thing*> inside OwningContainer, keep it in sync 
with the unique_ptr version, and return it in getThings(). (twice memory 
usage, slow, complicated, error prone)
3. Abandon unique_ptr inside of OwningContainer, and go back to manually 
managing the memory. (error prone and greatly increases development time)

Possible solutions to this include:
1. Add some kind of way to alias a unique_ptr<T> into a T*. Letting me 
essentially convert an array_view<const unique_ptr<T>> to array_view<const 
T>. In terms of how the implementation actually works on the machine, this 
is a trivial no-op. In terms of language rules its a complete nightmare.
2. Provide a specialized unique_vector<T*> which essentially operates like 
vector<unique_ptr<T>>, but exposes T* in its const interface. Then we can 
construct array_view<const T> over vector<T> and unique_vector<T>. Hiding 
the ownership implementation details and avoiding the need to for 
artificial templates.  This would solve the immediate example I've shown, 
but I'm not sure if its too specific and leaves out other similar 
situations.

How would you solve these 2 issues?

Have you seen any other complexities show up in your code from adopting 
unique_ptr?

-- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/46a85060-631b-49e5-94f3-ab07429d8085%40isocpp.org.

------=_Part_185_1235225468.1490287099072
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t have a proposal or a real solution. This is mo=
re intended to highlight some of the problems related to unique ownership a=
nd move semantics.<div><br></div><div>1. Its too easy to accidentally use a=
 moved from object by mistake</div><div><br></div><div>Consider this code:<=
/div><div><br></div><div><div class=3D"prettyprint" style=3D"background-col=
or: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: sol=
id; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-=
by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Co=
ntainer</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">addThing</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">unique_ptr</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Thing</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> p</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">this</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">_things</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">push_back</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">move</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">p</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">));</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
if</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">logging_enabled</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">cout </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=
=3D"styled-by-prettify">&quot;Added thing &quot;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> p</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify">name</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #080;" class=3D"styled-by-prettify">&quot; &quot;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">foo</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&lt;&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&=
quot; &quot;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">bar</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">endl</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span><font color=3D"#6=
66600"></font></div></code></div><br>I&#39;ve seen this kind of bug many ti=
mes. Its very easy to write and the compiler provides no help to you. Even =
better since the bug is hidden when logging is disabled, it could easily pa=
ss into production. Its also somewhat of an expert problem when explaining =
to novices.</div><div><br></div><div>Now here&#39;s an attempt to fix the b=
ug the right way. But we still have a mistake! Again no help from the compi=
ler. Also unless you&#39;re really paying attention, a quick skim through t=
he code will likely miss this one.</div><div><br></div><div><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Container</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">addThing</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">unique_ptr</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Thing</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> pc </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> p</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify">get</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">this</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">_things</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">push_back</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">move</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">p</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">));</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">logging_enabled</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">cout </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&lt;&lt;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify=
">&quot;Added thing &quot;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&lt;&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> pc</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">name</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #080;" class=3D"styled-by-prettify">&quot; &quot;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> pc</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">foo</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&=
lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot; &quot;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">bar</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;&lt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">e=
ndl</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span></div></code></div><span class=3D"=
styled-by-prettify" style=3D"font-family: monospace; background-color: rgb(=
250, 250, 250); color: rgb(102, 102, 0);"><div><br></div><div><span style=
=3D"color: rgb(34, 34, 34); font-family: Arial, Helvetica, sans-serif; back=
ground-color: rgb(255, 255, 255);">After we move p into _things, we never n=
eed to touch p again. Unfortunately in this case and many others, we can&#3=
9;t really introduce scopes with {} to eliminate p from the local namespace=
 and prevent these kinds of bugs.=C2=A0</span></div><div><span style=3D"col=
or: rgb(34, 34, 34); font-family: Arial, Helvetica, sans-serif; background-=
color: rgb(255, 255, 255);"><br></span></div><div><span style=3D"color: rgb=
(34, 34, 34); font-family: Arial, Helvetica, sans-serif; background-color: =
rgb(255, 255, 255);">A possible solution here might be some kind of [[disca=
rd]] attribute or a std::move_final() which is std::move() + [[discard]] to=
gether. So that the compiler would warn on any use of p after the move.=C2=
=A0</span><br></div><div><span class=3D"styled-by-prettify" style=3D"font-f=
amily: monospace; background-color: rgb(250, 250, 250); color: rgb(102, 102=
, 0);"><br></span></div><br></span>2. unique_ptr&lt;T&gt; and T* being diff=
erent types can cause pessimizations because of language rules.</div><div><=
br></div><div>Of course its a good thing that these types are different. On=
e is an owner and one is not. Using a different type means we can enlist th=
e help of the compiler to enforce correctness.</div><div><br></div><div>Som=
etimes I have a container with keeps a set of unique_ptrs, and I want to vi=
ew that set.</div><div><br></div><div><div class=3D"prettyprint" style=3D"b=
ackground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bord=
er-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">OwningContainer</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettify">p=
ublic</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </s=
pan><font color=3D"#000088"><span style=3D"color: #000;" class=3D"styled-by=
-prettify">array_view</span></font><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">Thing</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt=
;&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> getT=
hings</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> _things</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">private</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 std</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify">unique_ptr</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Thing</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&gt;&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> _things</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
lass</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">NonOwningContai=
ner</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">public</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><font color=3D"#000=
088"><span style=3D"color: #000;" class=3D"styled-by-prettify">array_view</=
span></font><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Thing</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">*&gt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> getThings</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _things</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">private</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">vector</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Thing</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">*&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 _things</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span styl=
e=3D"color: #800;" class=3D"styled-by-prettify">//Out of line function, may=
be lives in a 3rd party library.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">array=
_view</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Thing</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">*&gt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> things</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> g</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">OwningC=
ontainer</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&a=
mp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> c</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">){</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 f</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">c</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">getThings</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">());</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//Compiler Error</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> h</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">NonOwningContainer</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> c</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 f</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
c</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">getThings</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">());</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">//Ok</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">}</span></div></code></div><br>The getThings()=
 method of OwningContainer and NonOwningContainer methods have the exact sa=
me semantics. We&#39;re getting a const view of the stored thing pointers. =
The returned objects are even bitwise and machine code (after optimization)=
 identical, but are &quot;marked up&quot; by the compiler with different ty=
pes.</div><div><br></div><div>From the limited perspective of the code call=
ing getThings(), whether or not the container owns the pointers is an imple=
mentation detail. The caller does not and should not care whether the point=
ers are stored raw, unique_ptr. He just wants to view the collection and do=
 something with it.</div><div><br></div><div>The big problem here is that t=
he return types of getThings() are different. This means that in a generic =
context, you need to start introducing templates in order to handle all pos=
sible pointer types. Adding templates complicates the code and slows down c=
ompile times.</div><div><br></div><div>Also since const unique_ptr&lt;T&gt;=
 and const T* are semantically and even bitwise identical, using templates =
here will unnecessarily bloat your code with 2 functions that do the exact =
same thing. This increases your binary size and puts more pressure on the i=
cache.</div><div><br></div><div>In this example, we must change f() to be a=
 template. Even though the actual compiled down machine code will be identi=
cal. The biggest problem I have with this example is that the problem comes=
 from artificial language rules and not physical limits about how hardware =
and memory works. That goes against the zero overhead principle of C++.</di=
v><div><br></div><div>In order to avoid making f() a template here, there a=
re a few options today we can try with OwningContainer:</div><div>1. Return=
 vector&lt;Thing*&gt; by value, doing a copy and memory allocations at ever=
y call. (very slow)</div><div>2. Store a second vector&lt;Thing*&gt; inside=
 OwningContainer, keep it in sync with the unique_ptr version, and return i=
t in getThings(). (twice memory usage, slow, complicated, error prone)</div=
><div>3. Abandon unique_ptr inside of OwningContainer, and go back to manua=
lly managing the memory. (error prone and greatly increases development tim=
e)</div><div><br></div><div>Possible solutions to this include:</div><div>1=
.. Add some kind of way to alias a unique_ptr&lt;T&gt; into a T*. Letting me=
 essentially convert an array_view&lt;const unique_ptr&lt;T&gt;&gt; to arra=
y_view&lt;const T&gt;. In terms of how the implementation actually works on=
 the machine, this is a trivial no-op. In terms of language rules its a com=
plete nightmare.</div><div>2. Provide a specialized unique_vector&lt;T*&gt;=
 which essentially operates like vector&lt;unique_ptr&lt;T&gt;&gt;, but exp=
oses T* in its const interface. Then we can construct array_view&lt;const T=
&gt; over vector&lt;T&gt; and unique_vector&lt;T&gt;. Hiding the ownership =
implementation details and avoiding the need to for artificial templates. =
=C2=A0This would solve the immediate example I&#39;ve shown, but I&#39;m no=
t sure if its too specific and leaves out other similar situations.</div><d=
iv><br></div><div>How would you solve these 2 issues?</div><div><br></div><=
div>Have you seen any other complexities show up in your code from adopting=
 unique_ptr?</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/46a85060-631b-49e5-94f3-ab07429d8085%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/46a85060-631b-49e5-94f3-ab07429d8085=
%40isocpp.org</a>.<br />

------=_Part_185_1235225468.1490287099072--

------=_Part_184_1227975421.1490287099071--

.
