220 29559 <CAKgx6BL_cWfkySo-UpzTdJFHaQHj1Yyho2oyUUN2c2mhq+P0bA@mail.gmail.com> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Domen Vrankar <domen.vrankar@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: Instantiation of default destructor
Date: Mon, 28 Nov 2016 19:52:17 +0100
Lines: 317
Approved: news@gmane.org
Message-ID: <CAKgx6BL_cWfkySo-UpzTdJFHaQHj1Yyho2oyUUN2c2mhq+P0bA@mail.gmail.com>
References: <CAKgx6B+8zzZ131-UZobmUvCgB4YeQ1+wTZadcuT6ieDCofDndg@mail.gmail.com>
 <1a7a1b18-c001-405e-8f7f-09c048c6ee14@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=001a1140fadceb813b054260fa25
X-Trace: blaine.gmane.org 1480359187 25398 195.159.176.226 (28 Nov 2016 18:53:07 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Mon, 28 Nov 2016 18:53:07 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBCHJ3Z4NUUFBBCX26HAQKGQEWZYRLZQ@isocpp.org Mon Nov 28 19:52:59 2016
Return-path: <std-proposals+bncBCHJ3Z4NUUFBBCX26HAQKGQEWZYRLZQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yb0-f200.google.com ([209.85.213.200])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCHJ3Z4NUUFBBCX26HAQKGQEWZYRLZQ@isocpp.org>)
	id 1cBR2u-0004ub-2N
	for gclcip-std-proposals@m.gmane.org; Mon, 28 Nov 2016 19:52:56 +0100
Original-Received: by mail-yb0-f200.google.com with SMTP id d128sf120233288ybh.6
        for <gclcip-std-proposals@m.gmane.org>; Mon, 28 Nov 2016 10:53:00 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=PVGAQrFH/xkqAiUAlLPF+kyL80kI6OYHMYD2D27gqoY=;
        b=B2IFLgj6cNx0nyQO8biBBZTMAYy/w8O+sp8DPkE+7nZHSgtQfuH3b57XB6tyKMlNdB
         KcRNHy/X/ZkOC/EmU/KXN1RZyDa8YcLcqhQ9iVFtRHctgUu8vAPDeWj/QZdufDAgnrpq
         buCFL18grXBo3qrx+qMITulBTGPzCuwBFXBIk0/83yg0dZcAhcXe+PrqhSJrBf1VhSbN
         hoMId1jEbJkv34bRjKKgZVnobHPUiABKlZ+DLjd5wr5w8JDYLVAbQbIUfs1chdQlEZcO
         JEDWga07mPTuOPlvoLnVx/XgAvaG+0Z127/L6zHq5qVVtUDCGmbW5e/jzjY4rmLq3i13
         Q2BA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=PVGAQrFH/xkqAiUAlLPF+kyL80kI6OYHMYD2D27gqoY=;
        b=X8WQYxpSE7heLLEIyr/j+FwL3UFUTGr2wr1r6hI0Plx9JqPpeAQ8hOBqDj24XFW2Sq
         2ldzC64QGZuCmq4v66+/esKMUHPlQBwNe28MsJ/ajAl9wf83s6q2SYwoeUCFvCI1IajQ
         CKDqYyFLB0coGCIzy49ucEt2BXDfc4qgQ4FewWbfQ76Up4OZPsVyFByUUJAHW7hRvqKe
         yN3ei/DdtgCUz3XnL67Iou1HNYJ83+jnA+9pnHl43DBJH78H7Wgy1yVyvSAyDzmqesoR
         Lci9+Qe5OnaERlvXk6dJHE5d+MLfpkv5an1kFVtAp+FusKr/zY6WQ8D5lATcDbMPSuSC
         UMHA==
X-Gm-Message-State: AKaTC0101LoJDHi/ofI2Kn6346zwXXK3fsP6AwV7G+LFWZ/6MRJepsZ+nNOD7gXLywOE3A==
X-Received: by 10.13.228.199 with SMTP id n190mr5892770ywe.80.1480359179511;
        Mon, 28 Nov 2016 10:52:59 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.36.17.73 with SMTP id 70ls3438351itf.3.gmail; Mon, 28 Nov 2016
 10:52:58 -0800 (PST)
X-Received: by 10.36.190.206 with SMTP id i197mr18223455itf.70.1480359178049;
        Mon, 28 Nov 2016 10:52:58 -0800 (PST)
Original-Received: from mail-io0-x235.google.com (mail-io0-x235.google.com. [2607:f8b0:4001:c06::235])
        by mx.google.com with ESMTPS id u186si19795936itf.113.2016.11.28.10.52.58
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Mon, 28 Nov 2016 10:52:58 -0800 (PST)
Received-SPF: pass (google.com: domain of domen.vrankar@gmail.com designates 2607:f8b0:4001:c06::235 as permitted sender) client-ip=2607:f8b0:4001:c06::235;
Original-Received: by mail-io0-x235.google.com with SMTP id a124so246268662ioe.2
        for <std-proposals@isocpp.org>; Mon, 28 Nov 2016 10:52:58 -0800 (PST)
X-Received: by 10.107.154.206 with SMTP id c197mr20248199ioe.97.1480359177583;
 Mon, 28 Nov 2016 10:52:57 -0800 (PST)
Original-Received: by 10.50.235.15 with HTTP; Mon, 28 Nov 2016 10:52:17 -0800 (PST)
In-Reply-To: <1a7a1b18-c001-405e-8f7f-09c048c6ee14@isocpp.org>
X-Original-Sender: Domen.Vrankar@gmail.com
X-Original-Authentication-Results: mx.google.com;       dkim=pass
 header.i=@gmail.com;       spf=pass (google.com: domain of
 domen.vrankar@gmail.com designates 2607:f8b0:4001:c06::235 as permitted
 sender) smtp.mailfrom=domen.vrankar@gmail.com;       dmarc=pass (p=NONE
 dis=NONE) header.from=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:29559
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/29559>

--001a1140fadceb813b054260fa25
Content-Type: text/plain; charset=UTF-8

2016-11-28 16:11 GMT+01:00 Nicol Bolas <jmckesson@gmail.com>:

>
>
> On Monday, November 28, 2016 at 7:14:55 AM UTC-5, Domen Vrankar wrote:
>>
>> Hi,
>>
>> In this video [1] <https://www.youtube.com/watch?v=8AjRD6mU96s> (time
>> 57:40) Jason Jurecka was talking about the need to write empty/defaulted
>> destructor in cpp file if you want to declare a class in header file, use
>> it in std::unique_ptr and include its declaration only in cpp file:
>>
>> //a.h
>> ...
>> class T;
>>
>> struct A
>> {
>> A(T* ptr_); // intentionally before A() constructor - see the question
>> below
>> A();
>> std::unique_ptr<T> ptr;
>> };
>> ...
>>
>> //a.cpp
>> #include "a.h"
>> #include "t.h" // declaration of T class
>> ...
>> A::A() {}
>> A::A(T* ptr_) : ptr{ptr_} {}
>> ...
>>
>> This won't work since default destructor is (if I understood the reason
>> why Tomasz Wota's example in the comment worked: [2]
>> <http://melpon.org/wandbox/permlink/k8UpfCT8DlYv1hv3>) implemented at
>> the end of the compilation unit.
>>
>> For me it's not a big deal to write A::~A() = default; in cpp file but
>> still since we've had that debate I was wondering if it would be feasible
>> to change the wording (don't know how much the standard would have to be
>> changed for that) so that implicit default destructor would be added to the
>> code at the point of first constructor implementation (in the above example
>> at the point of A::A(T* ptr_); implementation in .cpp file) and not at the
>> end of the file where the class was declared?
>>
>>
> You've misunderstood the nature of the problem.
>

> The default destructor will call `unique_ptr::~unique_ptr`. And that
> destructor will call `T::~T()`. The problem is that, unless `T` has been
> *defined*, you cannot call its destructor.
>

I understand that but I always expected that it has to be known at the
point of destructor call like you would declare a variable before using it.

So having this structure:

//a.h
// guard & include memory
struct B;
struct A
{
  A();
  std::shared_ptr<B> ptr;
};

//a.cpp
#include "a.h"
#include "b.h"
A::A() : ptr{new B} {}

//b.h
// guard & include iostream
struct B{~B(){std::cout << "foo\n";}};

I would expect this to work:

// main.cpp
#include "b.h"
#include "a.h"
int main() {A a;}

But wouldn't expect this to work:

//main.cpp
#include "a.h"
int main() {A a;} // destructor chain called after the closing brace
#include "b.h" // B was not known until this point but the example still
works

But this wasn't the case that I was talking about (in this case you still
have to include b.h in the code where struct A is used).


> If the compiler defines the destructor for `A`, then it will do so in the
> class definition. That is, in the header. Which means that anyone who
> includes this header who doesn't include the definition of `T` beforehand
> will get a compile error.
>
> By declaring the destructor of `A` in the header, then defaulting the
> destructor in the .cpp, you force the compiler to only generate the class's
> destructor in the .cpp file. Where you have presumably included the
> definition of `T`. And thus, people can use `A` without necessarily having
> the full definition of `T`.
>
> And this was my question regarding the feasibility of a proposal. I'm not
a compiler writer so I might be talking nonsense (I remember something
regarding compilers not being happy about needing to remember stuff).

Current functionality is like you've described it above. What I was talking
about is this:

//a.h
// guard & include memory
struct B;
struct A
{
  A();
  // implicit declaration (not implementation as currently) of destructor
  // same as writing ~A(); so compiler remembers this point and binds it to
the
  // first constructor implementation
  std::shared_ptr<B> ptr;
};

//a.cpp
#include "a.h"
#include "b.h"
A::A() : ptr{new B} {}
// since compiler comes across first constructor implementation
// it generates destructor implementation here - same as writing A::~A() =
default;

Also in such case I would expect writing ~A() = default; work the same way
(split between declaration in header and implementation generation at the
same location as the example above.

This would work the same way as if currently declaring destructor ~A(); in
class/structure and defaulting it on the location where the first
constructor is declared (in case of an implicit or defaulted constructor
that would still mean getting the same error as currently but in the case
of implementing/defaulting the constructor in .cpp file it would work as if
currently defaulting the destructor in .cpp file - which means not needing
to include the header file all over the place).

Alternatively the defaulting of all implicit/defaulted functions could be
deferred until compiler reaches the implementation of the first function
that was only declared inside of the class but not implemented (if it
exists or at the end of the class declaration if it doesn't) but that would
probably mean even greater compilation overhead.

The benefit of this that I see would be that less people would even stumble
on this issue but the drawback would probably be larger compiler memory
footprint and compilation time.

I'm guessing that it wouldn't be feasible and it's not worth pursuing this
but as I said I'm not familiar with compiler internals so I prefer to ask
here first instead of drawing guesswork conclusions.
Am I correct regarding not being feasible?
Also is this even the correct mailing list for something like this or
should I next time write it on std-discussion mailing list?

Thanks,
Domen

-- 
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/CAKgx6BL_cWfkySo-UpzTdJFHaQHj1Yyho2oyUUN2c2mhq%2BP0bA%40mail.gmail.com.

--001a1140fadceb813b054260fa25
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">2016-11-28 16:11 GMT+01:00 Nicol Bolas <span dir=3D"ltr">&=
lt;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail=
..com</a>&gt;</span>:<br><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span=
 class=3D"gmail-"><br><br>On Monday, November 28, 2016 at 7:14:55 AM UTC-5,=
 Domen Vrankar wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div=
 dir=3D"ltr"><div><div>Hi,<br><br></div>In this video <a href=3D"https://ww=
w.youtube.com/watch?v=3D8AjRD6mU96s" rel=3D"nofollow" target=3D"_blank">[1]=
</a> (time 57:40) Jason Jurecka was talking about the need to write empty/d=
efaulted destructor in cpp file if you want to declare a class in header fi=
le, use it in std::unique_ptr and include its declaration only in cpp file:=
<br><br></div><div>//a.h<br>...<br></div><div>class T;<br><br></div><div>st=
ruct A<br></div><div>{<br>A(T* ptr_); // intentionally before A() construct=
or - see the question below<br></div><div>A();</div><div>std::unique_ptr&lt=
;T&gt; ptr;<br></div><div>};<br></div><div>...<br><br></div><div>//a.cpp<br=
></div><div>#include &quot;a.h&quot;<br></div><div>#include &quot;t.h&quot;=
 // declaration of T class<br></div><div>...<br></div><div>A::A() {}<br></d=
iv><div>A::A(T* ptr_) : ptr{ptr_} {}<br></div><div>...<br><br></div><div>Th=
is won&#39;t work since default destructor is (if I understood the reason w=
hy Tomasz Wota&#39;s example in the comment worked: <a href=3D"http://melpo=
n.org/wandbox/permlink/k8UpfCT8DlYv1hv3" rel=3D"nofollow" target=3D"_blank"=
>[2]</a>) implemented at the end of the compilation unit.<br><br></div><div=
>For me it&#39;s not a big deal to write A::~A() =3D default; in cpp file b=
ut still since we&#39;ve had that debate I was wondering if it would be fea=
sible to change the wording (don&#39;t know how much the standard would hav=
e to be changed for that) so that implicit default destructor would be adde=
d to the code at the point of first constructor implementation (in the abov=
e example at the point of A::A(T* ptr_); implementation in .cpp file) and n=
ot at the end of the file where the class was declared?</div><br></div></bl=
ockquote></span><div><br>You&#39;ve misunderstood the nature of the problem=
.. <br></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div><br>The default destructor will call `unique_pt=
r::~unique_ptr`. And that destructor will call `T::~T()`. The problem is th=
at, unless `T` has been <i>defined</i>, you cannot call its destructor.<br>=
</div></div></blockquote><div><br></div><div>I understand that but I always=
 expected that it has to be known at the point of destructor call like you =
would declare a variable before using it.<br><br></div><div>So having this =
structure:<br><br></div><div>//a.h<br></div><div>// guard &amp; include mem=
ory<br></div><div>struct B;<br><span class=3D"gmail-">struct A<br>{<br></sp=
an></div><div><span class=3D"gmail-">=C2=A0 A();<br></span></div><div><span=
 class=3D"gmail-">=C2=A0 std::shared</span>_ptr&lt;B&gt; ptr;<br>};<br><br>=
</div><div>//a.cpp<br></div><div>#include &quot;a.h&quot;<br></div><div>#in=
clude &quot;b.h&quot;<br>A::A() : ptr{new B} {}<br></div><div><br></div><di=
v>//b.h<br>// guard &amp; include iostream<br></div><div>struct B{~B(){std:=
:cout &lt;&lt; &quot;foo\n&quot;;}};<br><br></div><div>I would expect this =
to work:<br></div><div><br></div><div>// main.cpp<br></div><div>#include &q=
uot;b.h&quot;<br></div><div>#include &quot;a.h&quot;<br>int main() {A a;}<b=
r><br></div><div>But wouldn&#39;t expect this to work:<br><br></div><div>//=
main.cpp<br></div><div>#include &quot;a.h&quot;<br></div><div>int main() {A=
 a;} // destructor chain called after the closing brace<br></div><div>#incl=
ude &quot;b.h&quot; // B was not known until this point but the example sti=
ll works<br><br></div><div>But this wasn&#39;t the case that I was talking =
about (in this case you still have to include b.h in the code where struct =
A is used).<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><div>If the compiler defines the destructor f=
or `A`, then it will do so in the class definition. That is, in the header.=
 Which means that anyone who includes this header who doesn&#39;t include t=
he definition of `T` beforehand will get a compile error.<br><br>By declari=
ng the destructor of `A` in the header, then defaulting the destructor in t=
he .cpp, you force the compiler to only generate the class&#39;s destructor=
 in the .cpp file. Where you have presumably included the definition of `T`=
.. And thus, people can use `A` without necessarily having the full definiti=
on of `T`.<span class=3D"gmail-HOEnZb"><font color=3D"#888888"><br></font><=
/span></div></div><span class=3D"gmail-HOEnZb"><font color=3D"#888888">

<p></p>
</font></span></blockquote></div>And this was my question regarding the fea=
sibility of a proposal. I&#39;m not a compiler writer so I might be talking=
 nonsense (I remember something regarding compilers not being happy about n=
eeding to remember stuff).<br><br></div><div class=3D"gmail_extra">Current =
functionality is like you&#39;ve described it above. What I was talking abo=
ut is this:<br><br><div>//a.h<br></div><div>// guard &amp; include memory<b=
r></div><div>struct B;<br><span class=3D"gmail-">struct A<br>{<br></span></=
div><div><span class=3D"gmail-">=C2=A0 A();<br></span></div><div><span clas=
s=3D"gmail-">=C2=A0 // implicit declaration (not implementation as currentl=
y) of destructor<br>=C2=A0 // same as writing ~A(); so compiler remembers t=
his point and binds it to the<br></span></div><div><span class=3D"gmail-">=
=C2=A0 // first constructor implementation<br></span></div><div><span class=
=3D"gmail-">=C2=A0 std::shared</span>_ptr&lt;B&gt; ptr;<br>};<br><br></div>=
<div>//a.cpp<br></div><div>#include &quot;a.h&quot;<br></div>#include &quot=
;b.h&quot;<br>A::A() : ptr{new B} {}<br></div><div class=3D"gmail_extra">//=
 since compiler comes across first constructor implementation<br>// it gene=
rates destructor implementation here - same as writing A::~A() =3D default;=
<br><br></div><div class=3D"gmail_extra">Also in such case I would expect w=
riting ~A() =3D default; work the same way (split between declaration in he=
ader and implementation generation at the same location as the example abov=
e.<br></div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"=
>This would work the same way as if currently declaring destructor ~A(); in=
 class/structure and defaulting it on the location where the first construc=
tor is declared (in case of an implicit or defaulted constructor that would=
 still mean getting the same error as currently but in the case of implemen=
ting/defaulting the constructor in .cpp file it would work as if currently =
defaulting the destructor in .cpp file - which means not needing to include=
 the header file all over the place).</div><div class=3D"gmail_extra"><br><=
/div><div class=3D"gmail_extra">Alternatively the defaulting of all implici=
t/defaulted functions could be deferred until compiler reaches the implemen=
tation of the first function that was only declared inside of the class but=
 not implemented (if it exists or at the end of the class declaration if it=
 doesn&#39;t) but that would probably mean even greater compilation overhea=
d.<br></div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"=
>The benefit of this that I see would be that less people would even stumbl=
e on this issue but the drawback would probably be larger compiler memory f=
ootprint and compilation time.<br><br>I&#39;m guessing that it wouldn&#39;t=
 be feasible and it&#39;s not worth pursuing this but as I said I&#39;m not=
 familiar with compiler internals so I prefer to ask here first instead of =
drawing guesswork conclusions.<br></div><div class=3D"gmail_extra">Am I cor=
rect regarding not being feasible?<br></div><div class=3D"gmail_extra">Also=
 is this even the correct mailing list for something like this or should I =
next time write it on std-discussion mailing list?<br></div><div class=3D"g=
mail_extra"><br></div><div class=3D"gmail_extra">Thanks,<br></div><div clas=
s=3D"gmail_extra">Domen<br></div><div class=3D"gmail_extra"><br><br></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/CAKgx6BL_cWfkySo-UpzTdJFHaQHj1Yyho2oy=
UUN2c2mhq%2BP0bA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKgx6BL_cWfkyS=
o-UpzTdJFHaQHj1Yyho2oyUUN2c2mhq%2BP0bA%40mail.gmail.com</a>.<br />

--001a1140fadceb813b054260fa25--

.
