Topic: Non-nullable smart pointers
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Sun, 08 Mar 2015 10:24:40 +0300
Raw View
Hello everybody.
The problem I want you to discuss may have been already reviewed here,=20
but I did not found anything similar in the mailing list archive. I was=20
trying to explain the idea as well as I could, but I'm not a native=20
speaker, so I might fail at some points. Excuse me for that.
Have an nice weekend,
=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
=3D=3D=3D The problem =3D=3D=3D
This is a common practice in programming to check input parameters for
functions. As many parameters are pointers, smart or regular, checking
them against "nullptr" is a *very* frequent operation, but what should=20
you do if pointer is null? There are many options:
=E2=80=94 silently return from the function?
=E2=80=94 print warning message and return?
=E2=80=94 throw an exception?
=E2=80=94 call abort() from <cstdlib>?
=E2=80=94 use some kind of ASSERT() and hope it will do the right thing?
=E2=80=94 skip the check altogether and get a segfault in case?
The exact choice may be different for different projects but each has=20
its own drawbacks.
=E2=80=94 If you chose to silently return, can you be sure that this is s=
afe
for the caller to stay unaware? Missing required parameter is a
programmer's mistake and they should be told of it as soon as
possible.
=E2=80=94 If you chose to throw an exception, which one would you throw? =
Unlike
languages like Java, C# or Python, C++ has a relatively poor set of
predefined exceptions. It is also considered to be a good practice
in C++ to trow and exception only in case of really exceptional
situations and a single null pointer does not seem to be that much
serious matter. Moreover, when choosing exceptions you will have to
either pollute your functions' throw lists with std::invalid_argument
or just omit them entirely. The latter means it is easy for your code
user to forget to catch exceptions at all.
=E2=80=94 Calling abort(), directly or as result of ASSERT, is no better =
then
silently ignoring the error. I'm pretty sure nobody wants their
enterprise level system to shut down without even syncing disk cache
and database transactions due to forgotten null pointer passed to
logger function.
=E2=80=94 Ditto for not checking arguments at all.
=3D=3D=3D The proposed solution =3D=3D=3D
The problem could be completely eliminated in many cases if pointers=20
were not allowed to carry invalid values at all. These days C++ has a=20
strong movement toward smart pointers, leaving plain C pointers as a=20
legacy option or for very low-level things. Classes std::shared_ptr and=20
std::weak_ptr are commonly seen as a replacement.
Shared pointers are designed to mimic the behavior of plain pointers,=20
they can wrap any pointer, even the one which is not safe to deallocate=20
using "delete" operator. It offers its user a great number of ways to=20
misuse it.
I propose to create a subclass of shared pointers, which is somewhat=20
guaranteed to hold a valid object which can be safely deallocated. This=20
class should:
=E2=80=94 be unable to hold nullptr;
=E2=80=94 have no conversion constructors from plain pointers;
=E2=80=94 have object allocation to be the only way for pointer to be obt=
ained.
Lets call this class an std::object_ptr, after the term "object" which=20
is used throughout C++ standard text, and declare it like the following:
template <typename T>
class object_ptr: public std::shared_ptr<T> {
+ only copy and move constructors;
+ all operators applicable to std::shared_ptr<T>;
}
template <typename T, typename TAlloc, typename... TArgs>
object_ptr<T> allocate_object(const TAlloc& a, TArgs&&... args);
template <typename T, typename... TArgs>
object_ptr<T> make_object(TArgs&&... args);
The instance of the class must also be convertible to a shared pointer=20
which is never empty or null.
After the class is introduced, you may simply write your functions=20
arguments as std::object_ptr<T> if you expect them to be pointers to=20
valid objects only and just skip any further null-pointer validation, or=20
leave them as std::shared_ptr<T> in cases there nullability makes sense.=20
Or better use std::object_ptr together with std::optional, like the=20
following:
void Scene::paintSprite(const object_ptr<Sprite>&);
std::optional<std::shared_ptr<Sprite>>
Scene::findSprite(const Point&);
In the example above it is clear from the very declaration that painting=20
null sprite is not allowed (as being pointless) while function=20
"findSpline" can return sprite if it is able to find one, or can return=20
nothing otherwise.
We should also provide a way to create std::object_ptr from=20
std::shared_ptr or even plain pointers for legacy purposes, but there=20
should be the only one point there such a conversion is allowed. I'm not=20
quite sure about the exact name and signature, but it should be a single=20
function like that:
template <typename T>
std::object_ptr<T> object_ptr_cast(const std::shared_ptr<T>&)
throw(std::invalid_argument);
=3D=3D=3D Conclusion =3D=3D=3D
Eliminating null pointers validation may seem to be not that big deal to=20
create a special pointer type for that, but indeed it is a great=20
problem: thousands of people around the world, writing programs in=20
various languages, every day performs a lot of useless checks against=20
NULL, just to throw an exception which in most cases will never be=20
caught. We must do something to left those legacy checks behind and thus=20
improve code readability and "self-documentability".
To improve the situation, Java has introduced @NonNull arguments=20
attribute years ago (which is anyway broken), Scala uses the Optional[T]=20
pattern (as many other functional languages). There are languages like=20
Kotlin, which sees "T" as non-nulable reference by default and require=20
user to explicitly declare nullable references like "T?". (Moreover,=20
Kotlin can check arguments during compilation, with respect to code path=20
branching.) I think this approach will be widely adopted in the future=20
programming languages and C++ must take some steps in this direction.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sun, 8 Mar 2015 09:25:23 +0100
Raw View
When I read your message I asked myself why you couldn't just take the
arguments by reference?
Could you please explain that as well.
/MF
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Sun, 08 Mar 2015 11:47:28 +0300
Raw View
> When I read your message I asked myself why you couldn't just take the
> arguments by reference?
> Could you please explain that as well.
Because there is a lot of situations there you cannot pass or return by=20
reference. Consider the examples I've given:
=E2=80=94 you cannot pass argument to "addSprite" by reference because t=
he
sprite is supposed to be stored and controlled by the Scene once
after it has been added;
=E2=80=94 you cannot return a reference from "findSpline" function as th=
e
spline may be not found;
Moreover, references are very easy to misuse too: you can accidentally=20
return a reference to stack-allocated variable or create object on heap=20
and return it the caller which may (and will!) forget to delete the=20
allocated memory.
Of course, references remain still useful in many cases (an should be=20
used then appropriate), but not in the ones when you want to get rid of=20
object-ownership problems using reference-counting with smart pointers.
And one more note: reference can be invalid too if you employ some=20
trickery like null-pointer dereferencing (which can also be done=20
accidentally).
=E2=80=94=E2=80=94=E2=80=94 K. P.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 8 Mar 2015 09:32:09 -0700 (PDT)
Raw View
------=_Part_173_2117732955.1425832329986
Content-Type: multipart/alternative;
boundary="----=_Part_174_1672012319.1425832329986"
------=_Part_174_1672012319.1425832329986
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, March 8, 2015 at 3:24:45 AM UTC-4, Pavel Kretov wrote:
>
> Hello everybody.=20
>
> The problem I want you to discuss may have been already reviewed here,=20
> but I did not found anything similar in the mailing list archive. I was=
=20
> trying to explain the idea as well as I could, but I'm not a native=20
> speaker, so I might fail at some points. Excuse me for that.=20
>
> Have an nice weekend,=20
> =E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.=20
>
>
> =3D=3D=3D The problem =3D=3D=3D=20
>
> This is a common practice in programming to check input parameters for=20
> functions. As many parameters are pointers, smart or regular, checking=20
> them against "nullptr" is a *very* frequent operation, but what should=20
> you do if pointer is null? There are many options:=20
>
> =E2=80=94 silently return from the function?=20
> =E2=80=94 print warning message and return?=20
> =E2=80=94 throw an exception?=20
> =E2=80=94 call abort() from <cstdlib>?=20
> =E2=80=94 use some kind of ASSERT() and hope it will do the right thing=
?=20
> =E2=80=94 skip the check altogether and get a segfault in case?
>
If a function takes a pointer type, and it cannot work if it is given a=20
NULL pointer, then what has happened here is a violation of the implicit=20
contract between the function and whomever called it. And a violation of=20
this contract represents a program error, which means that the program is=
=20
no longer in a reasonable state.
Therefore, the program needs to halt execution.
=20
> The exact choice may be different for different projects but each has=20
> its own drawbacks.=20
>
> =E2=80=94 If you chose to silently return, can you be sure that this is=
safe=20
> for the caller to stay unaware? Missing required parameter is a=20
> programmer's mistake and they should be told of it as soon as=20
> possible.=20
>
> =E2=80=94 If you chose to throw an exception, which one would you throw=
? Unlike=20
> languages like Java, C# or Python, C++ has a relatively poor set of=
=20
> predefined exceptions. It is also considered to be a good practice=20
> in C++ to trow and exception only in case of really exceptional=20
> situations and a single null pointer does not seem to be that much=20
> serious matter. Moreover, when choosing exceptions you will have to=
=20
> either pollute your functions' throw lists with std::invalid_argument=
=20
> or just omit them entirely. The latter means it is easy for your code=
=20
> user to forget to catch exceptions at all.=20
>
If the user doesn't catch an exception, the application halts. If the=20
application can't halt, then that's the problem of the user. That being=20
said, I wouldn't throw an exception just for a NULL pointer. A pointer=20
being not-NULL is a precondition, and a violation of a precondition should=
=20
not result in an exception.
It should result (in debug) in program termination.
Also, "functions' throw lists" are no longer part of C++.
=20
>
> =E2=80=94 Calling abort(), directly or as result of ASSERT, is no bette=
r then=20
> silently ignoring the error. I'm pretty sure nobody wants their=20
> enterprise level system to shut down without even syncing disk cache=
=20
> and database transactions due to forgotten null pointer passed to=20
> logger function.
>
If you're talking about an application that isn't allowed to terminate,=20
then that means that your contract with the outside world needs to be=20
permissive. Which means you have to accept NULL and define what should=20
happen when you're given it. So you need to figure out how to do something=
=20
innocuous if you get a bad parameter.
Even so, most "enterprise applications" won't tolerate random pointers=20
being NULL anyway. They check where they're supposed to: at the interface=
=20
level. Once past the interface, everything is expected to be sane.
=20
> =E2=80=94 Ditto for not checking arguments at all.=20
>
>
> =3D=3D=3D The proposed solution =3D=3D=3D=20
>
> The problem could be completely eliminated in many cases if pointers=20
> were not allowed to carry invalid values at all. These days C++ has a=20
> strong movement toward smart pointers, leaving plain C pointers as a=20
> legacy option or for very low-level things. Classes std::shared_ptr and=
=20
> std::weak_ptr are commonly seen as a replacement.=20
>
> Shared pointers are designed to mimic the behavior of plain pointers,=20
> they can wrap any pointer, even the one which is not safe to deallocate=
=20
> using "delete" operator. It offers its user a great number of ways to=20
> misuse it.=20
>
> I propose to create a subclass of shared pointers, which is somewhat=20
> guaranteed to hold a valid object which can be safely deallocated. This=
=20
> class should:=20
>
> =E2=80=94 be unable to hold nullptr;=20
> =E2=80=94 have no conversion constructors from plain pointers;=20
> =E2=80=94 have object allocation to be the only way for pointer to be o=
btained.
>
And what if I already have a pointer, perhaps obtained via transfer of=20
ownership from the outside world? Or if I need to use a special deleter on=
=20
it?
Why not just have the constructor that takes a pointer check for NULL and=
=20
fail if it sees it? It can be explicit (just like shared_ptr's pointer=20
constructor), so it can't accidentally acquire ownership.
=20
> Lets call this class an std::object_ptr, after the term "object" which=20
> is used throughout C++ standard text, and declare it like the following:=
=20
>
> template <typename T>=20
> class object_ptr: public std::shared_ptr<T> {=20
> + only copy and move constructors;=20
> + all operators applicable to std::shared_ptr<T>;=20
> }=20
>
> template <typename T, typename TAlloc, typename... TArgs>=20
> object_ptr<T> allocate_object(const TAlloc& a, TArgs&&... args);=20
>
> template <typename T, typename... TArgs>=20
> object_ptr<T> make_object(TArgs&&... args);=20
>
> The instance of the class must also be convertible to a shared pointer=20
> which is never empty or null.=20
>
> After the class is introduced, you may simply write your functions=20
> arguments as std::object_ptr<T> if you expect them to be pointers to=20
> valid objects only and just skip any further null-pointer validation, or=
=20
> leave them as std::shared_ptr<T> in cases there nullability makes sense.=
=20
> Or better use std::object_ptr together with std::optional, like the=20
> following:=20
>
> void Scene::paintSprite(const object_ptr<Sprite>&);=20
>
> std::optional<std::shared_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> In the example above it is clear from the very declaration that painting=
=20
> null sprite is not allowed (as being pointless) while function=20
> "findSpline" can return sprite if it is able to find one, or can return=
=20
> nothing otherwise.
>
So... what does it mean to have an optional pointer that is committed (ie:=
=20
has a value), but that value is NULL?
It makes no sense to use optional with an object that already has the=20
concept of an empty state, unless there needs to be a distinction between=
=20
"empty" and "not-applicable". So if you need to return an object or not an=
=20
object... why would you not just return the shared_ptr?
> We should also provide a way to create std::object_ptr from=20
> std::shared_ptr or even plain pointers for legacy purposes, but there=20
> should be the only one point there such a conversion is allowed. I'm not=
=20
> quite sure about the exact name and signature, but it should be a single=
=20
> function like that:=20
>
> template <typename T>=20
> std::object_ptr<T> object_ptr_cast(const std::shared_ptr<T>&)=20
> throw(std::invalid_argument);=20
>
> =3D=3D=3D Conclusion =3D=3D=3D=20
>
> Eliminating null pointers validation may seem to be not that big deal to=
=20
> create a special pointer type for that, but indeed it is a great=20
> problem: thousands of people around the world, writing programs in=20
> various languages, every day performs a lot of useless checks against=20
> NULL, just to throw an exception which in most cases will never be=20
> caught.
=20
I disagree with the idea that this is necessarily common (or at least, that=
=20
it *has* to be). It is far more common to pass an object to a function=20
without transferring ownership to it. In such cases, a reference is=20
entirely appropriate.
Given the above, if you're passing a pointer, then it's usually something=
=20
that is one of the following: 1) can't be a reference (for some reason,=20
like a naked C array or whatever), 2) is conceptually nullable (and=20
therefore, the function is expecting to take a possibly null pointer), or=
=20
3) is a transfer of ownership. The cases you're worried about are #1 and #3=
..
I don't think they happen often enough to require the creation of a whole=
=20
new object type.
We must do something to left those legacy checks behind and thus=20
> improve code readability and "self-documentability".=20
>
> To improve the situation, Java has introduced @NonNull arguments=20
> attribute years ago (which is anyway broken), Scala uses the Optional[T]=
=20
> pattern (as many other functional languages). There are languages like=20
> Kotlin, which sees "T" as non-nulable reference by default and require=20
> user to explicitly declare nullable references like "T?". (Moreover,=20
> Kotlin can check arguments during compilation, with respect to code path=
=20
> branching.) I think this approach will be widely adopted in the future=20
> programming languages and C++ must take some steps in this direction.
>
C++ already has non-nullable references; they're called *references*. Sure,=
=20
you can *force* a reference to be NULL, but that generally requires deep,=
=20
personal stupidity. And C++ has never prevented a programmer from falling=
=20
victim to deep, personal stupidity.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_174_1672012319.1425832329986
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, March 8, 2015 at 3:24:45 AM UTC-4, Pavel Kretov=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hello everybody.
<br>
<br>The problem I want you to discuss may have been already reviewed here,=
=20
<br>but I did not found anything similar in the mailing list archive. I was=
=20
<br>trying to explain the idea as well as I could, but I'm not a native=20
<br>speaker, so I might fail at some points. Excuse me for that.
<br>
<br>Have an nice weekend,
<br>=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
<br>
<br>
<br>=3D=3D=3D The problem =3D=3D=3D
<br>
<br>This is a common practice in programming to check input parameters for
<br>functions. As many parameters are pointers, smart or regular, checking
<br>them against "nullptr" is a *very* frequent operation, but what should=
=20
<br>you do if pointer is null? There are many options:
<br>
<br> =E2=80=94 silently return from the function?
<br> =E2=80=94 print warning message and return?
<br> =E2=80=94 throw an exception?
<br> =E2=80=94 call abort() from <cstdlib>?
<br> =E2=80=94 use some kind of ASSERT() and hope it will do the righ=
t thing?
<br> =E2=80=94 skip the check altogether and get a segfault in case?<=
br></blockquote><div><br>If a function takes a pointer type, and it cannot =
work if it is given a NULL pointer, then what has happened here is a violat=
ion of the implicit contract between the function and whomever called it. A=
nd a violation of this contract represents a program error, which means tha=
t the program is no longer in a reasonable state.<br><br>Therefore, the pro=
gram needs to halt execution.<br> </div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;">
The exact choice may be different for different projects but each has=20
<br>its own drawbacks.
<br>
<br> =E2=80=94 If you chose to silently return, can you be sure that =
this is safe
<br> for the caller to stay unaware? Missing required paramete=
r is a
<br> programmer's mistake and they should be told of it as soo=
n as
<br> possible.
<br>
<br> =E2=80=94 If you chose to throw an exception, which one would yo=
u throw? Unlike
<br> languages like Java, C# or Python, C++ has a relatively p=
oor set of
<br> predefined exceptions. It is also considered to be a good=
practice
<br> in C++ to trow and exception only in case of really excep=
tional
<br> situations and a single null pointer does not seem to be =
that much
<br> serious matter. Moreover, when choosing exceptions you wi=
ll have to
<br> either pollute your functions' throw lists with std::inva=
lid_argument
<br> or just omit them entirely. The latter means it is easy f=
or your code
<br> user to forget to catch exceptions at all.
<br></blockquote><div><br>If the user doesn't catch an exception, the appli=
cation halts. If the application can't halt, then that's the problem of the=
user. That being said, I wouldn't throw an exception just for a NULL point=
er. A pointer being not-NULL is a precondition, and a violation of a precon=
dition should not result in an exception.<br><br>It should result (in debug=
) in program termination.<br><br>Also, "functions' throw lists" are no long=
er part of C++.<br> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
>
<br> =E2=80=94 Calling abort(), directly or as result of ASSERT, is n=
o better then
<br> silently ignoring the error. I'm pretty sure nobody wants=
their
<br> enterprise level system to shut down without even syncing=
disk cache
<br> and database transactions due to forgotten null pointer p=
assed to
<br> logger function.<br></blockquote><div><br>If you're talki=
ng about an application that isn't allowed to terminate, then that means th=
at your contract with the outside world needs to be permissive. Which means=
you have to accept NULL and define what should happen when you're given it=
.. So you need to figure out how to do something innocuous if you get a bad =
parameter.<br><br>Even so, most "enterprise applications" won't tolerate ra=
ndom pointers being NULL anyway. They check where they're supposed to: at t=
he interface level. Once past the interface, everything is expected to be s=
ane.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=E2=80=94 Ditto for not checking arguments at all.
<br>
<br>
<br>=3D=3D=3D The proposed solution =3D=3D=3D
<br>
<br>The problem could be completely eliminated in many cases if pointers=20
<br>were not allowed to carry invalid values at all. These days C++ has a=
=20
<br>strong movement toward smart pointers, leaving plain C pointers as a=20
<br>legacy option or for very low-level things. Classes std::shared_ptr and=
=20
<br>std::weak_ptr are commonly seen as a replacement.
<br>
<br>Shared pointers are designed to mimic the behavior of plain pointers,=
=20
<br>they can wrap any pointer, even the one which is not safe to deallocate=
=20
<br>using "delete" operator. It offers its user a great number of ways to=
=20
<br>misuse it.
<br>
<br>I propose to create a subclass of shared pointers, which is somewhat=20
<br>guaranteed to hold a valid object which can be safely deallocated. This=
=20
<br>class should:
<br>
<br> =E2=80=94 be unable to hold nullptr;
<br> =E2=80=94 have no conversion constructors from plain pointers;
<br> =E2=80=94 have object allocation to be the only way for pointer =
to be obtained.<br></blockquote><div><br>And what if I already have a point=
er, perhaps obtained via transfer of ownership from the outside world? Or i=
f I need to use a special deleter on it?<br><br>Why not just have the const=
ructor that takes a pointer check for NULL and fail if it sees it? It can b=
e explicit (just like shared_ptr's pointer constructor), so it can't accide=
ntally acquire ownership.<br> </div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;">
Lets call this class an std::object_ptr, after the term "object" which=20
<br>is used throughout C++ standard text, and declare it like the following=
:
<br>
<br> template <typename T>
<br> class object_ptr: public std::shared_ptr<T> {
<br> + only copy and move constructors;
<br> + all operators applicable to std::sh=
ared_ptr<T>;
<br> }
<br>
<br> template <typename T, typename TAlloc, typename.=
... TArgs>
<br> object_ptr<T> allocate_object(const TAlloc&am=
p; a, TArgs&&... args);
<br>
<br> template <typename T, typename... TArgs>
<br> object_ptr<T> make_object(TArgs&&... =
args);
<br>
<br>The instance of the class must also be convertible to a shared pointer=
=20
<br>which is never empty or null.
<br>
<br>After the class is introduced, you may simply write your functions=20
<br>arguments as std::object_ptr<T> if you expect them to be pointers=
to=20
<br>valid objects only and just skip any further null-pointer validation, o=
r=20
<br>leave them as std::shared_ptr<T> in cases there nullability makes=
sense.=20
<br>Or better use std::object_ptr together with std::optional, like the=20
<br>following:
<br>
<br> void Scene::paintSprite(const object_ptr<Sprite&=
gt;&);
<br>
<br> std::optional<std::shared_<wbr>ptr<Sprite>=
>
<br> Scene::findSprite(const Point&);
<br>
<br>In the example above it is clear from the very declaration that paintin=
g=20
<br>null sprite is not allowed (as being pointless) while function=20
<br>"findSpline" can return sprite if it is able to find one, or can return=
=20
<br>nothing otherwise.<br></blockquote><div><br>So... what does it mean to =
have an optional pointer that is committed (ie: has a value), but that valu=
e is NULL?<br><br>It makes no sense to use optional with an object that alr=
eady has the concept of an empty state, unless there needs to be a distinct=
ion between "empty" and "not-applicable". So if you need to return an objec=
t or not an object... why would you not just return the shared_ptr?<br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>We should also provide a way to create std::object_ptr from=20
<br>std::shared_ptr or even plain pointers for legacy purposes, but there=
=20
<br>should be the only one point there such a conversion is allowed. I'm no=
t=20
<br>quite sure about the exact name and signature, but it should be a singl=
e=20
<br>function like that:
<br>
<br> template <typename T>
<br> std::object_ptr<T> object_ptr_cast(const std:=
:shared_ptr<T>&)
<br> &=
nbsp; throw(s=
td::invalid_argument);
<br>
<br>=3D=3D=3D Conclusion =3D=3D=3D
<br>
<br>Eliminating null pointers validation may seem to be not that big deal t=
o=20
<br>create a special pointer type for that, but indeed it is a great=20
<br>problem: thousands of people around the world, writing programs in=20
<br>various languages, every day performs a lot of useless checks against=
=20
<br>NULL, just to throw an exception which in most cases will never be=20
<br>caught.</blockquote><div> </div><div>I disagree with the idea that=
this is necessarily common (or at least, that it <i>has</i> to be). It is =
far more common to pass an object to a function without transferring owners=
hip to it. In such cases, a reference is entirely appropriate.<br><br>Given=
the above, if you're passing a pointer, then it's usually something that i=
s one of the following: 1) can't be a reference (for some reason, like a na=
ked C array or whatever), 2) is conceptually nullable (and therefore, the f=
unction is expecting to take a possibly null pointer), or 3) is a transfer =
of ownership. The cases you're worried about are #1 and #3.<br><br>I don't =
think they happen often enough to require the creation of a whole new objec=
t type.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">We must d=
o something to left those legacy checks behind and thus=20
<br>improve code readability and "self-documentability".
<br>
<br>To improve the situation, Java has introduced @NonNull arguments=20
<br>attribute years ago (which is anyway broken), Scala uses the Optional[T=
]=20
<br>pattern (as many other functional languages). There are languages like=
=20
<br>Kotlin, which sees "T" as non-nulable reference by default and require=
=20
<br>user to explicitly declare nullable references like "T?". (Moreover,=20
<br>Kotlin can check arguments during compilation, with respect to code pat=
h=20
<br>branching.) I think this approach will be widely adopted in the future=
=20
<br>programming languages and C++ must take some steps in this direction.<b=
r></blockquote><div><br>C++ already has non-nullable references; they're ca=
lled <i>references</i>. Sure, you can <i>force</i> a reference to be NULL, =
but that generally requires deep, personal stupidity. And C++ has never pre=
vented a programmer from falling victim to deep, personal stupidity.<br></d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_174_1672012319.1425832329986--
------=_Part_173_2117732955.1425832329986--
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Sun, 08 Mar 2015 22:51:43 +0300
Raw View
Thank you for your long, detailed response.
As a foreword to my answer I'd like to say that my proposal is not to
replace old good references with a custom template class, but to replace
std::shared_ptr in many cases with its non-nullable version. I feel
strong about making non-nullable pointer the default option with
nullable pointer as a special case. I don't consider regular pointers as
I believe that future programs will use them exceptionally rare.
> If a function takes a pointer type, and it cannot work if it is
> given a NULL pointer, then what has happened here is a violation of
> the implicit contract between the function and whomever called it.
> And a violation of this contract represents a program error, which
> means that the program is no longer in a reasonable state.
The point is to turn that implicit contract into an explicit one. Now it
can be frequently seen in functions' documentation comments:
/// @param ptr: Pointer to something, must not be null.
This is the implicit contract, it is nice and easy, until you want to
actually enforce it. Doing that leads to great deal of problems, or you
will end up with a halted program.
> Therefore, the program needs to halt execution.
In some cases you don't really want the entire program to halt, but, for
example, to unload the plugin, cleanup after it and reload, while
sending the programmer a happy letter about an accident. Never letting
such a situation happen due to just a missed null pointer seems to be a
better approach to me, as these days programmers have a lot of much more
serious problems then dealing with null pointers.
> If the user doesn't catch an exception, the application halts. If the
> application can't halt, then that's the problem of the user. That
> being said, I wouldn't throw an exception just for a NULL pointer. A
> pointer being not-NULL is a precondition, and a violation of a
> precondition should not result in an exception.
>
> It should result (in debug) in program termination.
And what would you do in release? "Live fast die young" is suitable not
for each program. Nobody is guaranteed against accidental invalid
pointer, the proposal is to eliminate the problem entirely.
> Also, "functions' throw lists" are no longer part of C++.
Okay, my fault. Thank to you for teaching me the difference between
"throw()" and "noexcept" =E2=80=94 the former is deprecated :). But you you
still unable to mark function with "noexcept" keyword if you throw an
exception when checking nullable parameters.
> If you're talking about an application that isn't allowed to
> terminate, then that means that your contract with the outside world
> needs to be permissive. Which means you have to accept NULL and
> define what should happen when you're given it. So you need to
> figure out how to do something innocuous if you get a bad parameter.
That permissiveness makes code paths more complex and can lead to
undesired consequences. For example, you have got invalid pointer as a
constructor parameters, what would you do? You cannot cancel object
construction, but you don't want to construct invalid object either. So
you have to add more logic to you class to distinguish between properly
constructed objects and failback-constructed objects. Or throw an
exception which you generally dislike to do.
> Even so, most "enterprise applications" won't tolerate random
> pointers being NULL anyway. They check where they're supposed to: at
> the interface level. Once past the interface, everything is expected
> to be sane.
I understand that. Proposed pointers do the same thing: they are
guaranteed to be valid, no further checks needed at all neither on level
of the interface, nor below levels. Moreover, the interface is clearly
determined to accept only valid pointers, not nulls.
> And what if I already have a pointer, perhaps obtained via transfer
> of ownership from the outside world? Or if I need to use a special
> deleter on it?
>
> Why not just have the constructor that takes a pointer check for
> NULL and fail if it sees it? It can be explicit (just like
> shared_ptr's pointer constructor), so it can't accidentally acquire
> ownership.
We should definitely have the way to archive this, but I personally
would prefer to separate it from object_ptr class, just to make it
*extremely* clear for user that this is a point there ownership is
acquired or re-acquired. Given that, the object_ptr itself can stand
free from checks and exception-raising.
> We should also provide a way to create std::object_ptr from
> std::shared_ptr or even plain pointers for legacy purposes, but
> there should be the only one point there such a conversion is
> allowed. I'm not quite sure about the exact name and signature, but
> it should be a single function like that:
>
> template <typename T> std::object_ptr<T> object_ptr_cast(const
> std::shared_ptr<T>&) throw(std::invalid_argument);
>
> (Me, 2015-03-08 10:24:45 UTC+4)
This is the function proposed to get non-nullable pointers from the
nullable ones. I think it should be picked with more appropriate name
(it is not really a cast, as I feel), with more elaborated signature and
overloads. Overloaded version may include parameters to pass a custom
deleter and have other features from shared_ptr<T> constructors which
are absent from object_ptr.
> It makes no sense to use optional with an object that already has the
> concept of an empty state, unless there needs to be a distinction
> between "empty" and "not-applicable". So if you need to return an
> object or not an object... why would you not just return the
> shared_ptr?
Ops, I have a mistake in my example, sorry.
- std::optional<std::shared_ptr<Sprite>>
+ std::optional<std::object_ptr<Sprite>>
Scene::findSprite(const Point&);
Now it makes sense. Moreover, object_ptr can play really well with
std::optional. If object_ptr is ever going to become widely adopted,
optional+object_ptr would be better option then plain std::shared_ptr.
Compare:
std::optional<std::object_ptr<Sprite>>
Scene::findSprite(const Point&);
auto maybeSprite =3D scene.findSprite(point);
if (maybeSprite)
scene2.addSprite(maybeSprite.value());
with:
std::shared_ptr<Sprite>>
Scene::findSprite(const Point&);
auto sprite =3D scene.findSprite(point);
if (sprite)
scene2.addSprite(std::object_ptr_case(sprite));
^ Ugly part here.
The former case lets you completely avoid object_ptr to shared_ptr
conversions, without an additional object creation.
> I disagree with the idea that this is necessarily common (or at
> least, that it *has* to be). It is far more common to pass an object
> to a function without transferring ownership to it. In such cases, a
> reference is entirely appropriate.
I'm not about not using references there they should be.
> Given the above, if you're passing a pointer, then it's usually
> something that is one of the following: 1) can't be a reference (for
> some reason, like a naked C array or whatever), 2) is conceptually
> nullable (and therefore, the function is expecting to take a
> possibly null pointer), or 3) is a transfer of ownership. The cases
> you're worried about are #1 and #3.
>
> I don't think they happen often enough to require the creation of a
> whole new object type.
But they are often, at least the third one. If it wasn't, no smart
pointers would be introduced to the language at all.
> C++ already has non-nullable references; they're called
> *references*.
How do you call a reference with reference counting?
> Sure, you can *force* a reference to be NULL, but that generally
> requires deep, personal stupidity. And C++ has never prevented a
> programmer from falling victim to deep, personal stupidity.
Likewise, you are free to create an object_ptr instance holding null
pointer by using direct memory access (or famous "#define private
public" technique). Nobody can forbid you to shoot in your foot, but
that kind of shooting should be made as hard as possible in order to
safe others from the ricochet.
=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 8 Mar 2015 16:01:05 -0700 (PDT)
Raw View
------=_Part_41_1898790184.1425855665718
Content-Type: multipart/alternative;
boundary="----=_Part_42_1359628068.1425855665718"
------=_Part_42_1359628068.1425855665718
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I think "object_ptr" is very much the wrong name. Why? A big part of the=20
problem is that the name obliterates the most important word in its=20
predecessor: *shared*. What ownership semantics does "object_ptr" have:=20
shared, unique, none, something else? What would you name the "unique_ptr"=
=20
analog to "object_ptr", or the "weak_ptr" equivalent? You'll still need=20
those to complete your interface (well, maybe not "weak_ptr"; that one you=
=20
can probably reuse).
It seems to me that what you are proposing is something analogous to=20
std::reference_wrapper: a handle to an object that undeniably exists. You=
=20
asked in your post how you have a reference-counted reference. Well, isn't=
=20
that exactly what you're proposing?
Pointers are how you refer to objects that might not be there. References=
=20
are how you refer to objects that *must* exist. Even though language=20
references are not rebindable after creation, std::reference_wrapper is. So=
=20
it's very much the same concept as what you want, only without the=20
ownership semantics.
In short, std::reference_wrapper is the std::observer_ptr of owning objects=
=20
that have reference semantics (rather than pointer semantics).
So I think what you're proposing would be better called "shared_ref".=20
You'll also need "unique_ref", possibly "weak_ref", and certainly=20
"observer_ref" as a typedef of "reference_wrapper" to complete the set.
Oh, you should still have explicit conversions from the equivalent _ptr=20
types (obviously the "unique_" ones will require moves from their alternate=
=20
types). And certainly, shared_ref should share memory with shared_ptr and=
=20
vice-versa. They both ought to use the same back-end.
The only difference is that, if you hand them a NULL pointer, they'll throw=
=20
something.
On Sunday, March 8, 2015 at 3:51:49 PM UTC-4, Pavel Kretov wrote:
>
> Thank you for your long, detailed response.=20
> As a foreword to my answer I'd like to say that my proposal is not to=20
> replace old good references with a custom template class, but to replace=
=20
> std::shared_ptr in many cases with its non-nullable version. I feel=20
> strong about making non-nullable pointer the default option with=20
> nullable pointer as a special case. I don't consider regular pointers as=
=20
> I believe that future programs will use them exceptionally rare.=20
>
> > If a function takes a pointer type, and it cannot work if it is=20
> > given a NULL pointer, then what has happened here is a violation of=20
> > the implicit contract between the function and whomever called it.=20
> > And a violation of this contract represents a program error, which=20
> > means that the program is no longer in a reasonable state.=20
>
> The point is to turn that implicit contract into an explicit one. Now it=
=20
> can be frequently seen in functions' documentation comments:=20
>
> /// @param ptr: Pointer to something, must not be null.=20
>
> This is the implicit contract, it is nice and easy, until you want to=20
> actually enforce it. Doing that leads to great deal of problems, or you=
=20
> will end up with a halted program.=20
>
> > Therefore, the program needs to halt execution.=20
>
> In some cases you don't really want the entire program to halt, but, for=
=20
> example, to unload the plugin, cleanup after it and reload, while=20
> sending the programmer a happy letter about an accident.
This is where your example runs into a bit of a problem.
Your interface takes this "never non-NULL smart pointer." OK. So to call=20
your function, they must wrap their existing pointer in a "never non-NULL=
=20
smart pointer" pointer.
So rather than this:
shard_ptr<T> p =3D ... //Pointer already existed somewhere.
CallThatCantHandleNULL(p);
You want:
shared_ptr<T> p =3D ...//Pointer already existed somewhere.
CallThatCantHandleNULL(std::object_ptr_cast(p));
So what happens if 'p' is NULL?
Oh sure, it's NULL on the caller's end rather than in your function. But=20
the application stops just the same either way. Either they get an=20
exception that they don't catch, or they get an exception that they do=20
catch. It would have been no different on their end one way or another.
The only way this class solves the problem is if the user is *always* using=
=20
it. If they used it from the moment they got that pointer, and passed it=20
along to you that way.
But shared_ptr beat you to it. It's already there, with lots of people=20
using it for memory management. Not to mention the innumerable books and=20
teaching materials beating "shared_ptr" into people's heads. Without=20
widespread adoption of the type, the problem doesn't really get fixed.
=20
> Never letting=20
> such a situation happen due to just a missed null pointer seems to be a=
=20
> better approach to me, as these days programmers have a lot of much more=
=20
> serious problems then dealing with null pointers.=20
>
> > If the user doesn't catch an exception, the application halts. If the=
=20
> > application can't halt, then that's the problem of the user. That=20
> > being said, I wouldn't throw an exception just for a NULL pointer. A=20
> > pointer being not-NULL is a precondition, and a violation of a=20
> > precondition should not result in an exception.=20
> >=20
> > It should result (in debug) in program termination.=20
>
> And what would you do in release? "Live fast die young" is suitable not=
=20
> for each program. Nobody is guaranteed against accidental invalid=20
> pointer, the proposal is to eliminate the problem entirely.=20
>
> > Also, "functions' throw lists" are no longer part of C++.=20
>
> Okay, my fault. Thank to you for teaching me the difference between=20
> "throw()" and "noexcept" =E2=80=94 the former is deprecated :). But you y=
ou=20
> still unable to mark function with "noexcept" keyword if you throw an=20
> exception when checking nullable parameters.
>
Well, you shouldn't be marking functions "noexcept" frequently to begin=20
with. But even if you want it to be noexcept, let it. noexcept doesn't mean=
=20
"nothing gets thrown beyond this point". It means "if an exception gets=20
past me, kill the application." Therefore, the onus would be on the=20
implementer of the function to catch any exceptions that he doesn't want to=
=20
terminate the app.
> > If you're talking about an application that isn't allowed to=20
> > terminate, then that means that your contract with the outside world=20
> > needs to be permissive. Which means you have to accept NULL and=20
> > define what should happen when you're given it. So you need to=20
> > figure out how to do something innocuous if you get a bad parameter.=20
>
> That permissiveness makes code paths more complex and can lead to=20
> undesired consequences. For example, you have got invalid pointer as a=20
> constructor parameters, what would you do? You cannot cancel object=20
> construction,
Yes, you can. It's called "throwing an exception".
=20
> but you don't want to construct invalid object either. So=20
> you have to add more logic to you class to distinguish between properly=
=20
> constructed objects and failback-constructed objects. Or throw an=20
> exception which you generally dislike to do.=20
>
Maybe *you* generally dislike it. But it's the correct way to handle=20
invalid arguments passed to a constructor. We shouldn't add features to the=
=20
language to support misuse of the language.
> And what if I already have a pointer, perhaps obtained via transfer=20
> > of ownership from the outside world? Or if I need to use a special=20
> > deleter on it?=20
> >=20
> > Why not just have the constructor that takes a pointer check for=20
> > NULL and fail if it sees it? It can be explicit (just like=20
> > shared_ptr's pointer constructor), so it can't accidentally acquire=20
> > ownership.=20
>
> We should definitely have the way to archive this, but I personally=20
> would prefer to separate it from object_ptr class, just to make it=20
> *extremely* clear for user that this is a point there ownership is=20
> acquired or re-acquired.
But it is extremely clear; you're putting it in a *smart pointer*. The=20
typename has to be explicitly stated if it's an explicit constructor.
It's kind of a big sign: 'std::shared_ref{p}'. You can't possibly miss it.=
=20
It's certainly no more noticeable than 'std::shared_ref_cast(p)'
Given that, the object_ptr itself can stand free from checks and=20
> exception-raising.=20
>
But by doing it in the constructor, you can fix one of the problems you=20
cited originally: the lack of a specific exception for the particular=20
condition of a NULL pointer where there shouldn't be one.
You don't want to encourage people to write their own wrapper functions,=20
which will all use independent exceptions.
I simply don't see an advantage of a free function here over an explicit=20
constructor.=20
> It makes no sense to use optional with an object that already has the=20
> > concept of an empty state, unless there needs to be a distinction=20
> > between "empty" and "not-applicable". So if you need to return an=20
> > object or not an object... why would you not just return the=20
> > shared_ptr?=20
>
> Ops, I have a mistake in my example, sorry.=20
>
> - std::optional<std::shared_ptr<Sprite>>=20
> + std::optional<std::object_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> Now it makes sense. Moreover, object_ptr can play really well with=20
> std::optional. If object_ptr is ever going to become widely adopted,=20
> optional+object_ptr would be better option then plain std::shared_ptr.=20
>
> Compare:=20
>
> std::optional<std::object_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> auto maybeSprite =3D scene.findSprite(point);=20
> if (maybeSprite)=20
> scene2.addSprite(maybeSprite.value());=20
>
> with:=20
>
> std::shared_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> auto sprite =3D scene.findSprite(point);=20
> if (sprite)=20
> scene2.addSprite(std::object_ptr_case(sprite));=20
> ^ Ugly part here.=20
>
> The former case lets you completely avoid object_ptr to shared_ptr=20
> conversions, without an additional object creation.
>
This is another reason why I suggest "shared_ref" rather than "object_ptr".=
=20
Because what you're making when you combine it with optional is the=20
infamous std::optional<T&>.
Only it's done in a way that's not terrible ;)
> I disagree with the idea that this is necessarily common (or at=20
> > least, that it *has* to be). It is far more common to pass an object=20
> > to a function without transferring ownership to it. In such cases, a=20
> > reference is entirely appropriate.=20
>
> I'm not about not using references there they should be.=20
>
> > Given the above, if you're passing a pointer, then it's usually=20
> > something that is one of the following: 1) can't be a reference (for=20
> > some reason, like a naked C array or whatever), 2) is conceptually=20
> > nullable (and therefore, the function is expecting to take a=20
> > possibly null pointer), or 3) is a transfer of ownership. The cases=20
> > you're worried about are #1 and #3.=20
> >=20
> > I don't think they happen often enough to require the creation of a=20
> > whole new object type.=20
>
> But they are often, at least the third one. If it wasn't, no smart=20
> pointers would be introduced to the language at all.
>
There's a difference between "not often" and "never". We need smart=20
pointers because we *sometimes* need to transfer ownership. But the overall=
=20
goal should be to limit such times to the bare minimum required.
The vast majority of parameters are (or should be) taken by value or by=20
reference. By smart pointer is, compared to all parameters used in an API,=
=20
a relatively rare occurrence. Yes, it does happen. But it doesn't happen so=
=20
frequently that you need a whole new type to cover "by smart pointer,=20
previously assured to not be NULL".
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_42_1359628068.1425855665718
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I think "object_ptr" is very much the wrong name. Why? A b=
ig part of the problem is that the name obliterates the most important word=
in its predecessor: <i>shared</i>. What ownership semantics does "object_p=
tr" have: shared, unique, none, something else? What would you name the "un=
ique_ptr" analog to "object_ptr", or the "weak_ptr" equivalent? You'll stil=
l need those to complete your interface (well, maybe not "weak_ptr"; that o=
ne you can probably reuse).<br><br>It
seems to me that what you are proposing is something analogous to=20
std::reference_wrapper: a handle to an object that undeniably exists.=20
You asked in your post how you have a reference-counted reference. Well, is=
n't
that exactly what you're proposing?<br><br>Pointers are how you refer=20
to objects that might not be there. References are how you refer to=20
objects that *must* exist. Even though language references are not=20
rebindable after creation, std::reference_wrapper is. So it's very much the=
same concept as what you want, only without the ownership semantics.<br><b=
r>In short, std::reference_wrapper is the std::observer_ptr of owning objec=
ts that have reference semantics (rather than pointer semantics).<br><br>So=
I think=20
what you're proposing would be better called "shared_ref". You'll also need=
"unique_ref", possibly "weak_ref", and certainly "observer_ref" as a typed=
ef of "reference_wrapper" to complete the set.<br><br>Oh, you should still=
=20
have explicit conversions from the equivalent _ptr types (obviously the "un=
ique_" ones will require moves from their alternate types). And certainly, =
shared_ref
should share memory with shared_ptr and vice-versa. They both ought to=20
use the same back-end.<br><br>The only difference is that, if you hand them=
a NULL pointer, they'll throw something.<br><br>On Sunday, March 8, 2015 a=
t 3:51:49 PM UTC-4, Pavel Kretov wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;">Thank you for your long, detailed response.
<br>As a foreword to my answer I'd like to say that my proposal is not to
<br>replace old good references with a custom template class, but to replac=
e
<br>std::shared_ptr in many cases with its non-nullable version. I feel
<br>strong about making non-nullable pointer the default option with
<br>nullable pointer as a special case. I don't consider regular pointers a=
s
<br>I believe that future programs will use them exceptionally rare.
<br>
<br>> If a function takes a pointer type, and it cannot work if it is
<br>> given a NULL pointer, then what has happened here is a violation o=
f
<br>> the implicit contract between the function and whomever called it.
<br>> And a violation of this contract represents a program error, which
<br>> means that the program is no longer in a reasonable state.
<br>
<br>The point is to turn that implicit contract into an explicit one. Now i=
t
<br>can be frequently seen in functions' documentation comments:
<br>
<br> /// @param ptr: Pointer to something, must not be n=
ull.
<br>
<br>This is the implicit contract, it is nice and easy, until you want to
<br>actually enforce it. Doing that leads to great deal of problems, or you
<br>will end up with a halted program.
<br>
<br>> Therefore, the program needs to halt execution.
<br>
<br>In some cases you don't really want the entire program to halt, but, fo=
r
<br>example, to unload the plugin, cleanup after it and reload, while
<br>sending the programmer a happy letter about an accident.</blockquote><d=
iv><br>This is where your example runs into a bit of a problem.<br><br>Your=
interface takes this "never non-NULL smart pointer." OK. So to call your f=
unction, they must wrap their existing pointer in a "never non-NULL smart p=
ointer" pointer.<br><br>So rather than this:<br><br>shard_ptr<T> p =
=3D ... //Pointer already existed somewhere.<br>CallThatCantHandleNULL(p);<=
br><br>You want:<br><br>shared_ptr<T> p =3D ...//Pointer already exis=
ted somewhere.<br>CallThatCantHandleNULL(std::object_ptr_cast(p));<br><br>S=
o what happens if 'p' is NULL?<br><br>Oh sure, it's NULL on the caller's en=
d rather than in your function. But the application stops just the same eit=
her way. Either they get an exception that they don't catch, or they get an=
exception that they do catch. It would have been no different on their end=
one way or another.<br><br>The only way this class solves the problem is i=
f the user is <i>always</i> using it. If they used it from the moment they =
got that pointer, and passed it along to you that way.<br><br>But shared_pt=
r beat you to it. It's already there, with lots of people using it for memo=
ry management. Not to mention the innumerable books and teaching materials =
beating "shared_ptr" into people's heads. Without widespread adoption of th=
e type, the problem doesn't really get fixed.<br> </div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">Never letting
<br>such a situation happen due to just a missed null pointer seems to be a
<br>better approach to me, as these days programmers have a lot of much mor=
e
<br>serious problems then dealing with null pointers.
<br>
<br>> If the user doesn't catch an exception, the application halts. If =
the
<br>> application can't halt, then that's the problem of the user. That
<br>> being said, I wouldn't throw an exception just for a NULL pointer.=
A
<br>> pointer being not-NULL is a precondition, and a violation of a
<br>> precondition should not result in an exception.
<br>>
<br>> It should result (in debug) in program termination.
<br>
<br>And what would you do in release? "Live fast die young" is suitable not
<br>for each program. Nobody is guaranteed against accidental invalid
<br>pointer, the proposal is to eliminate the problem entirely.
<br>
<br>> Also, "functions' throw lists" are no longer part of C++.
<br>
<br>Okay, my fault. Thank to you for teaching me the difference between
<br>"throw()" and "noexcept" =E2=80=94 the former is deprecated :). But you=
you
<br>still unable to mark function with "noexcept" keyword if you throw an
<br>exception when checking nullable parameters.<br></blockquote><div><br>W=
ell, you shouldn't be marking functions "noexcept" frequently to begin with=
.. But even if you want it to be noexcept, let it. noexcept doesn't mean "no=
thing gets thrown beyond this point". It means "if an exception gets past m=
e, kill the application." Therefore, the onus would be on the implementer o=
f the function to catch any exceptions that he doesn't want to terminate th=
e app.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> If you're talking about an application that isn't allowed to
<br>> terminate, then that means that your contract with the outside wor=
ld
<br>> needs to be permissive. Which means you have to accept NULL and
<br>> define what should happen when you're given it. So you need to
<br>> figure out how to do something innocuous if you get a bad paramete=
r.
<br>
<br>That permissiveness makes code paths more complex and can lead to
<br>undesired consequences. For example, you have got invalid pointer as a
<br>constructor parameters, what would you do? You cannot cancel object
<br>construction,</blockquote><div><br>Yes, you can. It's called "throwing =
an exception".<br> </div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
but you don't want to construct invalid object either. So
<br>you have to add more logic to you class to distinguish between properly
<br>constructed objects and failback-constructed objects. Or throw an
<br>exception which you generally dislike to do.
<br></blockquote><div><br>Maybe <i>you</i> generally dislike it. But it's t=
he correct way to handle invalid arguments passed to a constructor. We shou=
ldn't add features to the language to support misuse of the language.<br><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> And what if I already have a pointer, perhaps obtained via transfer
<br>> of ownership from the outside world? Or if I need to use a special
<br>> deleter on it?
<br>>
<br>> Why not just have the constructor that takes a pointer check for
<br>> NULL and fail if it sees it? It can be explicit (just like
<br>> shared_ptr's pointer constructor), so it can't accidentally acquir=
e
<br>> ownership.
<br>
<br>We should definitely have the way to archive this, but I personally
<br>would prefer to separate it from object_ptr class, just to make it
<br>*extremely* clear for user that this is a point there ownership is
<br>acquired or re-acquired.</blockquote><div><br>But it is extremely clear=
; you're putting it in a <i>smart pointer</i>. The typename has to be expli=
citly stated if it's an explicit constructor.<br><br>It's kind of a big sig=
n: 'std::shared_ref{p}'. You can't possibly miss it. It's certainly no more=
noticeable than 'std::shared_ref_cast(p)'<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">Given that, the object_ptr itself can stand
free from checks and exception-raising.
<br></blockquote><div><br>But by doing it in the constructor, you can fix o=
ne of the problems you cited originally: the lack of a specific exception f=
or the particular condition of a NULL pointer where there shouldn't be one.=
<br><br>You don't want to encourage people to write their own wrapper funct=
ions, which will all use independent exceptions.<br><br>I simply don't see =
an advantage of a free function here over an explicit constructor. <br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> It makes no sense to use optional with an object that already has the
<br>> concept of an empty state, unless there needs to be a distinction
<br>> between "empty" and "not-applicable". So if you need to return an
<br>> object or not an object... why would you not just return the
<br>> shared_ptr?
<br>
<br>Ops, I have a mistake in my example, sorry.
<br>
<br>- std::optional<std::shared_ptr<<wbr>Sprite>>
<br>+ std::optional<std::object_ptr<<wbr>Sprite>>
<br> Scene::findSprite(const Point&);
<br>
<br>Now it makes sense. Moreover, object_ptr can play really well with
<br>std::optional. If object_ptr is ever going to become widely adopted,
<br>optional+object_ptr would be better option then plain std::shared_ptr.
<br>
<br>Compare:
<br>
<br> std::optional<std::object_<wbr>ptr<Sprite>=
>
<br> Scene::findSprite(const Point&);
<br>
<br> auto maybeSprite =3D scene.findSprite(point);
<br> if (maybeSprite)
<br> scene2.addSprite(maybeSprite.<wbr>val=
ue());
<br>
<br>with:
<br>
<br> std::shared_ptr<Sprite>>
<br> Scene::findSprite(const Point&);
<br>
<br> auto sprite =3D scene.findSprite(point);
<br> if (sprite)
<br> scene2.addSprite(std::object_<wbr>ptr=
_case(sprite));
<br> &=
nbsp; ^ Ugly part here.
<br>
<br>The former case lets you completely avoid object_ptr to shared_ptr
<br>conversions, without an additional object creation.<br></blockquote><di=
v><br>This is another reason why I suggest "shared_ref" rather than "object=
_ptr". Because what you're making when you combine it with optional is the =
infamous std::optional<T&>.<br><br>Only it's done in a way that's=
not terrible ;)<br><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> I disagree with the idea that this is necessarily common (or at
<br>> least, that it *has* to be). It is far more common to pass an obje=
ct
<br>> to a function without transferring ownership to it. In such cases,=
a
<br>> reference is entirely appropriate.
<br>
<br>I'm not about not using references there they should be.
<br>
<br>> Given the above, if you're passing a pointer, then it's usually
<br>> something that is one of the following: 1) can't be a reference (f=
or
<br>> some reason, like a naked C array or whatever), 2) is conceptually
<br>> nullable (and therefore, the function is expecting to take a
<br>> possibly null pointer), or 3) is a transfer of ownership. The case=
s
<br>> you're worried about are #1 and #3.
<br>>
<br>> I don't think they happen often enough to require the creation of =
a
<br>> whole new object type.
<br>
<br>But they are often, at least the third one. If it wasn't, no smart
<br>pointers would be introduced to the language at all.<br></blockquote><d=
iv><br>There's a difference between "not often" and "never". We need smart =
pointers because we <i>sometimes</i> need to transfer ownership. But the ov=
erall goal should be to limit such times to the bare minimum required.<br><=
br>The vast majority of parameters are (or should be) taken by value or by =
reference. By smart pointer is, compared to all parameters used in an API, =
a relatively rare occurrence. Yes, it does happen. But it doesn't happen so=
frequently that you need a whole new type to cover "by smart pointer, prev=
iously assured to not be NULL".<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_42_1359628068.1425855665718--
------=_Part_41_1898790184.1425855665718--
.
Author: Marc Mutz <marc.mutz@kdab.com>
Date: Mon, 9 Mar 2015 12:44:04 +0100
Raw View
On Sunday 08 March 2015 08:24:40 Pavel Kretov wrote:
> This is a common practice in programming to check input parameters for
> functions. As many parameters are pointers, smart or regular, checking
> them against "nullptr" is a very frequent operation, but what should
> you do if pointer is null? There are many options:
I was very much in favour of your idea until I read further. I thought you
were proposing a nonnull_ptr<T> which just wraps a T*, in the spriti of
Bjarne's Type-Rich Interface principle. But when I read "inheriting from
shared_ptr", I was disappointed.
What's wrong with
template <typename T>
class nonnull_ptr {
T *ptr;
public:
/* implicit */ nonnull_ptr(T *t) : ptr(t) { if (!t) std::terminate(); }
// or throw
// all you can do with a T*, except maybe pointer arithmetic
};
?
Thanks,
Marc
--
Marc Mutz <marc.mutz@kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-Independent Software Solutions
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 05:38:13 -0700 (PDT)
Raw View
------=_Part_3518_374287189.1425904693850
Content-Type: multipart/alternative;
boundary="----=_Part_3519_2086029585.1425904693851"
------=_Part_3519_2086029585.1425904693851
Content-Type: text/plain; charset=UTF-8
On Sunday, March 8, 2015 at 5:32:10 PM UTC+1, Nicol Bolas wrote:
>
> If the user doesn't catch an exception, the application halts. If the
> application can't halt, then that's the problem of the user. That being
> said, I wouldn't throw an exception just for a NULL pointer. A pointer
> being not-NULL is a precondition, and a violation of a precondition should
> not result in an exception.
>
> It should result (in debug) in program termination.
>
> I agree, but what's the proper way to do that?
assert doesn't generally work in release / NDEBUG mode and we don't have a
variant of assert that does.
I think that normal references are the answer to most of Pavel's problems
with pointers.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3519_2086029585.1425904693851
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, March 8, 2015 at 5:32:10 PM UTC+1, Nico=
l Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div>If the user doesn't catch an exception, the application halts. If the=
application can't halt, then that's the problem of the user. That being sa=
id, I wouldn't throw an exception just for a NULL pointer. A pointer being =
not-NULL is a precondition, and a violation of a precondition should not re=
sult in an exception.<br><br>It should result (in debug) in program termina=
tion.<br><br></div></div></blockquote><div>I agree, but what's the proper w=
ay to do that?</div><div>assert doesn't generally work in release / NDEBUG =
mode and we don't have a variant of assert that does.</div><div><br></div><=
div>I think that normal references are the answer to most of Pavel's proble=
ms with pointers. </div><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3519_2086029585.1425904693851--
------=_Part_3518_374287189.1425904693850--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 05:44:03 -0700 (PDT)
Raw View
------=_Part_324_1831236477.1425905043961
Content-Type: multipart/alternative;
boundary="----=_Part_325_2003323782.1425905043961"
------=_Part_325_2003323782.1425905043961
Content-Type: text/plain; charset=UTF-8
On Sunday, March 8, 2015 at 8:51:49 PM UTC+1, Pavel Kretov wrote:
>
> I don't consider regular pointers as
> I believe that future programs will use them exceptionally rare.
>
> I think you're wrong. Regular pointers are fine as long as they don't own
the pointee.
> This is the implicit contract, it is nice and easy, until you want to
> actually enforce it. Doing that leads to great deal of problems, or you
> will end up with a halted program.
>
> Most of the time a halted program is fine if bugs are encountered. Trying
to deal with such bugs in other ways is error-prone.
> > Therefore, the program needs to halt execution.
>
> In some cases you don't really want the entire program to halt, but, for
> example, to unload the plugin, cleanup after it and reload, while
> sending the programmer a happy letter about an accident. Never letting
> such a situation happen due to just a missed null pointer seems to be a
> better approach to me, as these days programmers have a lot of much more
> serious problems then dealing with null pointers.
>
Maybe, maybe not, but how would your non-nullable pointer solve this?
What does it do when you try to assign null anyway?
> That permissiveness makes code paths more complex and can lead to
> undesired consequences. For example, you have got invalid pointer as a
> constructor parameters, what would you do? You cannot cancel object
> construction, but you don't want to construct invalid object either. So
> you have to add more logic to you class to distinguish between properly
> constructed objects and failback-constructed objects. Or throw an
> exception which you generally dislike to do.
>
>
Why can't object construction fail?
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_325_2003323782.1425905043961
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, March 8, 2015 at 8:51:49 PM UTC+1, Pavel Kretov=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I don't consider regula=
r pointers as
<br>I believe that future programs will use them exceptionally rare.
<br>
<br></blockquote><div>I think you're wrong. Regular pointers are fine as lo=
ng as they don't own the pointee.</div><div> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">This is the implicit contract, it is nice and e=
asy, until you want to
<br>actually enforce it. Doing that leads to great deal of problems, or you
<br>will end up with a halted program.
<br>
<br></blockquote><div>Most of the time a halted program is fine if bugs are=
encountered. Trying to deal with such bugs in other ways is error-prone.</=
div><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> Ther=
efore, the program needs to halt execution.
<br>
<br>In some cases you don't really want the entire program to halt, but, fo=
r
<br>example, to unload the plugin, cleanup after it and reload, while
<br>sending the programmer a happy letter about an accident. Never letting
<br>such a situation happen due to just a missed null pointer seems to be a
<br>better approach to me, as these days programmers have a lot of much mor=
e
<br>serious problems then dealing with null pointers.
<br></blockquote><div><br></div><div>Maybe, maybe not, but how would your n=
on-nullable pointer solve this?</div><div>What does it do when you try to a=
ssign null anyway?</div><div> </div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;">That permissiveness makes code paths more complex and can lead t=
o
<br>undesired consequences. For example, you have got invalid pointer as a
<br>constructor parameters, what would you do? You cannot cancel object
<br>construction, but you don't want to construct invalid object either. So
<br>you have to add more logic to you class to distinguish between properly
<br>constructed objects and failback-constructed objects. Or throw an
<br>exception which you generally dislike to do.
<br>
<br></blockquote><div><br></div><div>Why can't object construction fail?</d=
iv><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_325_2003323782.1425905043961--
------=_Part_324_1831236477.1425905043961--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 05:47:16 -0700 (PDT)
Raw View
------=_Part_45_2065962952.1425905236814
Content-Type: multipart/alternative;
boundary="----=_Part_46_2123729568.1425905236814"
------=_Part_46_2123729568.1425905236814
Content-Type: text/plain; charset=UTF-8
On Monday, March 9, 2015 at 12:01:05 AM UTC+1, Nicol Bolas wrote:
>
> So I think what you're proposing would be better called "shared_ref".
> You'll also need "unique_ref", possibly "weak_ref", and certainly
> "observer_ref" as a typedef of "reference_wrapper" to complete the set.
>
What would weak_ref do if the pointee (referee?) is gone?
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_46_2123729568.1425905236814
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, March 9, 2015 at 12:01:05 AM UTC+1, Nic=
ol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">So I think=20
what you're proposing would be better called "shared_ref". You'll also need=
"unique_ref", possibly "weak_ref", and certainly "observer_ref" as a typed=
ef of "reference_wrapper" to complete the set.</div></blockquote><div><br><=
/div><div>What would weak_ref do if the pointee (referee?) is gone? </=
div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_46_2123729568.1425905236814--
------=_Part_45_2065962952.1425905236814--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 9 Mar 2015 06:49:28 -0700 (PDT)
Raw View
------=_Part_495_1328932959.1425908968031
Content-Type: multipart/alternative;
boundary="----=_Part_496_1546313113.1425908968032"
------=_Part_496_1546313113.1425908968032
Content-Type: text/plain; charset=UTF-8
On Monday, March 9, 2015 at 7:39:10 AM UTC-4, Marc Mutz wrote:
>
> On Sunday 08 March 2015 08:24:40 Pavel Kretov wrote:
> > This is a common practice in programming to check input parameters for
> > functions. As many parameters are pointers, smart or regular, checking
> > them against "nullptr" is a very frequent operation, but what should
> > you do if pointer is null? There are many options:
>
> I was very much in favour of your idea until I read further. I thought you
> were proposing a nonnull_ptr<T> which just wraps a T*, in the spriti of
> Bjarne's Type-Rich Interface principle. But when I read "inheriting from
> shared_ptr", I was disappointed.
>
> What's wrong with
>
> template <typename T>
> class nonnull_ptr {
> T *ptr;
> public:
> /* implicit */ nonnull_ptr(T *t) : ptr(t) { if (!t)
> std::terminate(); }
> // or throw
> // all you can do with a T*, except maybe pointer arithmetic
> };
>
> ?
>
> Thanks,
> Marc
That already exists; it's called a *reference*.
What he wants is something that a language reference can't provide:
transfer of ownership. He wants to transfer ownership of an object that
certainly exists.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_496_1546313113.1425908968032
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, March 9, 2015 at 7:39:10 AM UTC-4, Marc=
Mutz wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Sunday 08 March=
2015 08:24:40 Pavel Kretov wrote:
<br>> This is a common practice in programming to check input parameters=
for
<br>> functions. As many parameters are pointers, smart or regular, chec=
king
<br>> them against "nullptr" is a very frequent operation, but what shou=
ld=20
<br>> you do if pointer is null? There are many options:
<br>
<br>I was very much in favour of your idea until I read further. I thought =
you=20
<br>were proposing a nonnull_ptr<T> which just wraps a T*, in the spr=
iti of=20
<br>Bjarne's Type-Rich Interface principle. But when I read "inheriting fro=
m=20
<br>shared_ptr", I was disappointed.
<br>
<br>What's wrong with
<br>
<br> template <typename T>
<br> class nonnull_ptr {
<br> T *ptr;
<br> public:
<br> /* implicit */ nonnull_ptr(T *t) : ptr(t) { if (!t=
) std::terminate(); }=20
<br>// or throw
<br> // all you can do with a T*, except maybe pointer =
arithmetic
<br> };
<br>
<br>?
<br>
<br>Thanks,
<br>Marc </blockquote><div> <br>That already exists; it's called =
a <i>reference</i>.<br><br>What he wants is something that a language refer=
ence can't provide: transfer of ownership. He wants to transfer ownership o=
f an object that certainly exists.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_496_1546313113.1425908968032--
------=_Part_495_1328932959.1425908968031--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 9 Mar 2015 06:50:34 -0700 (PDT)
Raw View
------=_Part_444_1824546157.1425909034427
Content-Type: multipart/alternative;
boundary="----=_Part_445_1228265186.1425909034427"
------=_Part_445_1228265186.1425909034427
Content-Type: text/plain; charset=UTF-8
On Monday, March 9, 2015 at 8:38:13 AM UTC-4, Olaf van der Spek wrote:
>
>
>
> On Sunday, March 8, 2015 at 5:32:10 PM UTC+1, Nicol Bolas wrote:
>>
>> If the user doesn't catch an exception, the application halts. If the
>> application can't halt, then that's the problem of the user. That being
>> said, I wouldn't throw an exception just for a NULL pointer. A pointer
>> being not-NULL is a precondition, and a violation of a precondition should
>> not result in an exception.
>>
>> It should result (in debug) in program termination.
>>
>> I agree, but what's the proper way to do that?
> assert doesn't generally work in release / NDEBUG mode and we don't have a
> variant of assert that does.
>
If you need to kill an application, call std::terminate. This isn't hard.
I think that normal references are the answer to most of Pavel's problems
> with pointers.
>
As he specifically stated, he wants transfer-of-ownership semantics. And
presently, you only get that with pointers.
>
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_445_1228265186.1425909034427
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, March 9, 2015 at 8:38:13 AM UTC-4, Olaf=
van der Spek wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br><br>On Sunday, March 8, 2015 at 5:32:10 PM UTC+1, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>If the =
user doesn't catch an exception, the application halts. If the application =
can't halt, then that's the problem of the user. That being said, I wouldn'=
t throw an exception just for a NULL pointer. A pointer being not-NULL is a=
precondition, and a violation of a precondition should not result in an ex=
ception.<br><br>It should result (in debug) in program termination.<br><br>=
</div></div></blockquote><div>I agree, but what's the proper way to do that=
?</div><div>assert doesn't generally work in release / NDEBUG mode and we d=
on't have a variant of assert that does.</div></div></blockquote><div><br>I=
f you need to kill an application, call std::terminate. This isn't hard.<br=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><d=
iv>I think that normal references are the answer to most of Pavel's problem=
s with pointers. </div></div></blockquote><div><br>As he specifically =
stated, he wants transfer-of-ownership semantics. And presently, you only g=
et that with pointers.<br> </div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div> </div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_445_1228265186.1425909034427--
------=_Part_444_1824546157.1425909034427--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 9 Mar 2015 06:53:08 -0700 (PDT)
Raw View
------=_Part_501_412587031.1425909188392
Content-Type: multipart/alternative;
boundary="----=_Part_502_125533854.1425909188392"
------=_Part_502_125533854.1425909188392
Content-Type: text/plain; charset=UTF-8
On Monday, March 9, 2015 at 8:47:16 AM UTC-4, Olaf van der Spek wrote:
>
>
>
> On Monday, March 9, 2015 at 12:01:05 AM UTC+1, Nicol Bolas wrote:
>>
>> So I think what you're proposing would be better called "shared_ref".
>> You'll also need "unique_ref", possibly "weak_ref", and certainly
>> "observer_ref" as a typedef of "reference_wrapper" to complete the set.
>>
>
> What would weak_ref do if the pointee (referee?) is gone?
>
I did say probably ;)
It would return an optional<shared_ref<T>>. That has the same semantics as
shared_ptr, only reference-style.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_502_125533854.1425909188392
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, March 9, 2015 at 8:47:16 AM UTC-4, Olaf=
van der Spek wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br><br>On Monday, March 9, 2015 at 12:01:05 AM UTC+1, Nicol Bolas=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">So I think=
=20
what you're proposing would be better called "shared_ref". You'll also need=
"unique_ref", possibly "weak_ref", and certainly "observer_ref" as a typed=
ef of "reference_wrapper" to complete the set.</div></blockquote><div><br><=
/div><div>What would weak_ref do if the pointee (referee?) is gone? </=
div></div></blockquote><div><br>I did say probably ;) <br><br>It would retu=
rn an optional<shared_ref<T>>. That has the same semantics as s=
hared_ptr, only reference-style.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_502_125533854.1425909188392--
------=_Part_501_412587031.1425909188392--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 15:59:19 +0100
Raw View
2015-03-09 14:50 GMT+01:00 Nicol Bolas <jmckesson@gmail.com>:
> If you need to kill an application, call std::terminate. This isn't hard.
It's not hard, but I prefer something like assure(!p); over if (!p)
std::terminate();
Do debuggers break if one calls terminate or abort?
--
Olaf
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Mon, 09 Mar 2015 18:43:44 +0300
Raw View
>> I don't consider regular pointers as
>> I believe that future programs will use them exceptionally rare.
>>
> I think you're wrong. Regular pointers are fine as long as they don't own
> the pointee.
Regular pointers are fine when used appropriately. But they don't seem=20
appropriate for me in cases where their use would lead to a bunch of=20
ownership semantics problems. I'm not a foreteller, but I can see the=20
movement toward using smart pointers in C++ community.
>> This is the implicit contract, it is nice and easy, until you want to
>> actually enforce it. Doing that leads to great deal of problems, or you
>> will end up with a halted program.
>
> Most of the time a halted program is fine if bugs are encountered. Trying
> to deal with such bugs in other ways is error-prone.
Not always. You would probably want to do something to recover your=20
program from every possible and impossible error if that program is=20
leading the rocket to an orbit. (Quite edgy example, though.)
>>> Therefore, the program needs to halt execution.
>>
>> In some cases you don't really want the entire program to halt, but, for
>> example, to unload the plugin, cleanup after it and reload, while
>> sending the programmer a happy letter about an accident. Never letting
>> such a situation happen due to just a missed null pointer seems to be a
>> better approach to me, as these days programmers have a lot of much more
>> serious problems then dealing with null pointers.
>
> Maybe, maybe not, but how would your non-nullable pointer solve this?
> What does it do when you try to assign null anyway?
You cannot simply assign non-nullable pointer a value, but if you try to=20
construct one with from a null, you would get an exception. But if your=20
program uses non-nullable pointers wherever possible, you would need to=20
control this exception very rarely.
>> That permissiveness makes code paths more complex and can lead to
>> undesired consequences. For example, you have got invalid pointer as a
>> constructor parameters, what would you do? You cannot cancel object
>> construction, but you don't want to construct invalid object either. So
>> you have to add more logic to you class to distinguish between properly
>> constructed objects and failback-constructed objects. Or throw an
>> exception which you generally dislike to do.
>>
> Why can't object construction fail?
We were talking about "permissive" behavior on validation fail. Unlike=20
ordinary functions, for constructors you can either construct an object,=20
or don't (by throwing an exception), you cannot do something innocent=20
and pretend nothing happened.
=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Mon, 09 Mar 2015 18:46:23 +0300
Raw View
> I think "object_ptr" is very much the wrong name. Why? A big part of the
> problem is that the name obliterates the most important word in its
> predecessor: *shared*. What ownership semantics does "object_ptr" have:
> shared, unique, none, something else? What would you name the "unique_ptr=
"
> analog to "object_ptr", or the "weak_ptr" equivalent? You'll still need
> those to complete your interface (well, maybe not "weak_ptr"; that one yo=
u
> can probably reuse).
Maybe you're right. I was thinking a lot about choosing appropriate name=20
for this entity. I started from "notnull_ptr", then thought of=20
"shared_ref", but later decided it would be nice to employ term "object"=20
in the meaning which I remember from reading C standard text:
=C2=ABObject =E2=80=94 a region of data storage in the execution envir=
onment,
the contents of which can represent values. Except for bit-fields,
objects are composed of contiguous sequences of one or more bytes,
the number, order, and encoding of which are either explicitly
specified or implementation-defined.=C2=BB
But to my surprise, when I've checked C++ 2014 draft I did not find this=20
term. Name "shared_ref" seems to be appropriate for me, but we will be=20
unable to make it behave like real reference as we cannot overload=20
"operator.", it still will act like a pointer.
> It seems to me that what you are proposing is something analogous to
> std::reference_wrapper: a handle to an object that undeniably exists. You
> asked in your post how you have a reference-counted reference. Well, isn'=
t
> that exactly what you're proposing?
Not exactly. I was thinking about the class just like shared_ptr, but=20
without all that tedious validation checks.
> Pointers are how you refer to objects that might not be there. References
> are how you refer to objects that *must* exist. Even though language
> references are not rebindable after creation, std::reference_wrapper is. =
So
> it's very much the same concept as what you want, only without the
> ownership semantics.
But without ownership semantics the whole proposal looses its meaning.
> In short, std::reference_wrapper is the std::observer_ptr of owning objec=
ts
> that have reference semantics (rather than pointer semantics).
Just for my information, is "observer_ptr" proposal accepted? I've seen=20
its draft only.
> So I think what you're proposing would be better called "shared_ref".
> You'll also need "unique_ref", possibly "weak_ref", and certainly
> "observer_ref" as a typedef of "reference_wrapper" to complete the set.
> Oh, you should still have explicit conversions from the equivalent _ptr
> types (obviously the "unique_" ones will require moves from their alterna=
te
> types). And certainly, shared_ref should share memory with shared_ptr and
> vice-versa. They both ought to use the same back-end.
I was thinking about proposing such a companion type for "uniq_ptr" too=20
(I'm not sure about "weak_ptr"), but came to conclusion that "who would=20
store null in uniq_ptr?". May be I should think again, as the symmetry=20
you just shown would be quite nice.
> The only difference is that, if you hand them a NULL pointer, they'll thr=
ow
> something.
There is std::bad_weak_ptr already, maybe we should introduce just=20
"bad_pointer", or "bad_smart_pointer", or "bad_reference_cast"?
>> In some cases you don't really want the entire program to halt, but, for
>> example, to unload the plugin, cleanup after it and reload, while
>> sending the programmer a happy letter about an accident.
>
> This is where your example runs into a bit of a problem.
>
> Your interface takes this "never non-NULL smart pointer." OK. So to call
> your function, they must wrap their existing pointer in a "never non-NULL
> smart pointer" pointer.
>
> So rather than this:
>
> shared_ptr<T> p =3D ... //Pointer already existed somewhere.
> CallThatCantHandleNULL(p);
>
> You want:
>
> shared_ptr<T> p =3D ...//Pointer already existed somewhere.
> CallThatCantHandleNULL(std::object_ptr_cast(p));
>
> So what happens if 'p' is NULL?
I think an exception must be thrown. This is essential for this cast to=20
be called as rare as possible, only for compatibility with third-party=20
or legacy code, thus reducing number of points where such an exceptions=20
may be thrown. I'd prefer to perform this cast as a function (not as a=20
constructor) for user to be able easily locate such points in their code=20
(using grep or something like this).
If "shared_refs" are used in your code base consistently, as widely as=20
possible, employing std::optional instead of shared_ptr, then you would=20
hardly ever need to call that "cast" function except for legacy purposed.
> Oh sure, it's NULL on the caller's end rather than in your function. But
> the application stops just the same either way. Either they get an
> exception that they don't catch, or they get an exception that they do
> catch. It would have been no different on their end one way or another.
Yes, but the overall number of places there you catch these exceptions=20
would greatly reduce, as you are not obliged to try{} function calls,=20
but only the places where you create "shared_refs" from nullable pointers.
> The only way this class solves the problem is if the user is *always* usi=
ng
> it. If they used it from the moment they got that pointer, and passed it
> along to you that way.
> But shared_ptr beat you to it. It's already there, with lots of people
> using it for memory management. Not to mention the innumerable books and
> teaching materials beating "shared_ptr" into people's heads. Without
> widespread adoption of the type, the problem doesn't really get fixed.
You're freaking perfectly right. That is the sad part of story and the=20
reason why I wrote my proposal into the mailing list associated with C++=20
standard committee instead of my Facebook page. :)
> Well, you shouldn't be marking functions "noexcept" frequently to begin
> with. But even if you want it to be noexcept, let it. noexcept doesn't me=
an
> "nothing gets thrown beyond this point". It means "if an exception gets
> past me, kill the application." Therefore, the onus would be on the
> implementer of the function to catch any exceptions that he doesn't want =
to
> terminate the app.
Thank you once again for your explanation. I liked the idea of throw=20
lists a lot, given that that lists are to be checked by the compiler=20
whether possible. "Noexcept" seems to be quite different. It seems I=20
must read my C++ book once again.
>> That permissiveness makes code paths more complex and can lead to
>> undesired consequences. For example, you have got invalid pointer as a
>> constructor parameters, what would you do? You cannot cancel object
>> construction,
>
> Yes, you can. It's called "throwing an exception".
By "cancel" I mean early returning from a function (possibly with an=20
error code), but for constructors there is no such option.
>> but you don't want to construct invalid object either. So
>> you have to add more logic to you class to distinguish between properly
>> constructed objects and failback-constructed objects. Or throw an
>> exception which you generally dislike to do.
>
> Maybe *you* generally dislike it. But it's the correct way to handle
> invalid arguments passed to a constructor. We shouldn't add features to t=
he
> language to support misuse of the language.
This was a kind of answer to your "I'd prefer not throw an exception=20
just due to NULL pointer" (inaccurate quotation).
>> We should definitely have the way to archive this, but I personally
>> would prefer to separate it from object_ptr class, just to make it
>> *extremely* clear for user that this is a point there ownership is
>> acquired or re-acquired.
>
> But it is extremely clear; you're putting it in a *smart pointer*. The
> typename has to be explicitly stated if it's an explicit constructor.
>
> It's kind of a big sign: 'std::shared_ref{p}'. You can't possibly miss it=
..
> It's certainly no more noticeable than 'std::shared_ref_cast(p)'
Maybe you're right. This would be consistent with existing "shared_ptr"=20
behavior.
> But by doing it in the constructor, you can fix one of the problems you
> cited originally: the lack of a specific exception for the particular
> condition of a NULL pointer where there shouldn't be one.
>
> You don't want to encourage people to write their own wrapper functions,
> which will all use independent exceptions.
Certainly I don't. But even in constructor, which exception should I=20
throw when null pointer is passed?
> This is another reason why I suggest "shared_ref" rather than "object_ptr=
".
> Because what you're making when you combine it with optional is the
> infamous std::optional<T&>.
>
> Only it's done in a way that's not terrible ;)
Okay, way too many points to rename.
> The vast majority of parameters are (or should be) taken by value or by
> reference. By smart pointer is, compared to all parameters used in an API=
,
> a relatively rare occurrence. Yes, it does happen. But it doesn't happen =
so
> frequently that you need a whole new type to cover "by smart pointer,
> previously assured to not be NULL".
Maybe. (This was on "need a whole new type", not on "should be=20
[preferably] taken by value or reference".) But, as you see from our=20
discussion, how do you, personally, think, should I prepare the official=20
proposal or the whole idea is doomed?
=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 09 Mar 2015 09:05:25 -0700
Raw View
On Monday 09 March 2015 15:59:19 Olaf van der Spek wrote:
> Do debuggers break if one calls terminate or abort?
Yes, they usually do.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 17:41:16 +0100
Raw View
2015-03-09 16:43 GMT+01:00 Pavel Kretov <firegurafiku@gmail.com>:
>>> I don't consider regular pointers as
>>> I believe that future programs will use them exceptionally rare.
>>>
>> I think you're wrong. Regular pointers are fine as long as they don't own
>> the pointee.
>
>
> Regular pointers are fine when used appropriately. But they don't seem
> appropriate for me in cases where their use would lead to a bunch of
> ownership semantics problems. I'm not a foreteller, but I can see the
> movement toward using smart pointers in C++ community.
That does not contradict my statement.
> Not always. You would probably want to do something to recover your program
> from every possible and impossible error if that program is leading the
> rocket to an orbit. (Quite edgy example, though.)
I don't know, I'm not a rocket scientist. Are you?
Exception and dynamic memory are probably forbidden in those cases anyway..
Rockets might self-destruct or call a fatal error handler too, I don't
think they try to somehow ignore the error.
> You cannot simply assign non-nullable pointer a value, but if you try to
> construct one with from a null, you would get an exception. But if your
> program uses non-nullable pointers wherever possible, you would need to
> control this exception very rarely.
IMO the same is true for using normal smart pointers and normal
references. Issues with null pointers just don't come up often.
--
Olaf
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 17:45:09 +0100
Raw View
2015-03-09 17:05 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> On Monday 09 March 2015 15:59:19 Olaf van der Spek wrote:
>> Do debuggers break if one calls terminate or abort?
>
> Yes, they usually do.
$ ./a.out
Aborted
$ ./a.out
terminate called without an active exception
Aborted
$ ./a.out
a.out: b.cpp:6: int main(): Assertion `false' failed.
Aborted
I like the output of assert() better. Might be a toolchain issue though.
--
Olaf
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 9 Mar 2015 09:46:39 -0700 (PDT)
Raw View
------=_Part_44_547709515.1425919599594
Content-Type: multipart/alternative;
boundary="----=_Part_45_1238907563.1425919599594"
------=_Part_45_1238907563.1425919599594
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, March 9, 2015 at 11:47:13 AM UTC-4, Pavel Kretov wrote:
>
> > I think "object_ptr" is very much the wrong name. Why? A big part of th=
e=20
> > problem is that the name obliterates the most important word in its=20
> > predecessor: *shared*. What ownership semantics does "object_ptr" have:=
=20
> > shared, unique, none, something else? What would you name the=20
> "unique_ptr"=20
> > analog to "object_ptr", or the "weak_ptr" equivalent? You'll still need=
=20
> > those to complete your interface (well, maybe not "weak_ptr"; that one=
=20
> you=20
> > can probably reuse).=20
>
> Maybe you're right. I was thinking a lot about choosing appropriate name=
=20
> for this entity. I started from "notnull_ptr", then thought of=20
> "shared_ref", but later decided it would be nice to employ term "object"=
=20
> in the meaning which I remember from reading C standard text:=20
>
> =C2=ABObject =E2=80=94 a region of data storage in the execution env=
ironment,=20
> the contents of which can represent values. Except for bit-fields,=
=20
> objects are composed of contiguous sequences of one or more bytes,=
=20
> the number, order, and encoding of which are either explicitly=20
> specified or implementation-defined.=C2=BB=20
>
> But to my surprise, when I've checked C++ 2014 draft I did not find this=
=20
> term. Name "shared_ref" seems to be appropriate for me, but we will be=20
> unable to make it behave like real reference as we cannot overload=20
> "operator.", it still will act like a pointer.=20
>
You use it like it's a pointer. But outside of having to use ->, it will=20
behave like a reference: it will always refer to an object.
> Pointers are how you refer to objects that might not be there. References=
=20
> > are how you refer to objects that *must* exist. Even though language=20
> > references are not rebindable after creation, std::reference_wrapper is=
..=20
> So=20
> > it's very much the same concept as what you want, only without the=20
> > ownership semantics.=20
>
> But without ownership semantics the whole proposal looses its meaning.=20
>
I meant that std::reference_wrapper has no ownership semantics.
I also thought that std::reference_wrapper had an operator-> overload. It=
=20
doesn't.
> The only way this class solves the problem is if the user is *always*=20
> using=20
> > it. If they used it from the moment they got that pointer, and passed i=
t=20
> > along to you that way.=20
> > But shared_ptr beat you to it. It's already there, with lots of people=
=20
> > using it for memory management. Not to mention the innumerable books an=
d=20
> > teaching materials beating "shared_ptr" into people's heads. Without=20
> > widespread adoption of the type, the problem doesn't really get fixed.=
=20
>
> You're freaking perfectly right. That is the sad part of story and the=20
> reason why I wrote my proposal into the mailing list associated with C++=
=20
> standard committee instead of my Facebook page. :)=20
>
My point is that having the class and sticking it in a few interface=20
functions doesn't fix the problem. It has to be used consistently and=20
everywhere. And existing smart-pointers are already being widely used, so=
=20
it's an uphill battle to get everyone to suddenly use another=20
reference-counted object.
> Well, you shouldn't be marking functions "noexcept" frequently to begin=
=20
> > with. But even if you want it to be noexcept, let it. noexcept doesn't=
=20
> mean=20
> > "nothing gets thrown beyond this point". It means "if an exception gets=
=20
> > past me, kill the application." Therefore, the onus would be on the=20
> > implementer of the function to catch any exceptions that he doesn't wan=
t=20
> to=20
> > terminate the app.=20
>
> Thank you once again for your explanation. I liked the idea of throw=20
> lists a lot, given that that lists are to be checked by the compiler=20
> whether possible. "Noexcept" seems to be quite different. It seems I=20
> must read my C++ book once again.=20
>
No, it isn't. The same thing would happen in throw lists too (assuming your=
=20
compiler actually implemented them). If an exception other than a listed=20
one tried to escape the function, then std::terminate would be called.
=20
> > The vast majority of parameters are (or should be) taken by value or by=
=20
> > reference. By smart pointer is, compared to all parameters used in an=
=20
> API,=20
> > a relatively rare occurrence. Yes, it does happen. But it doesn't happe=
n=20
> so=20
> > frequently that you need a whole new type to cover "by smart pointer,=
=20
> > previously assured to not be NULL".=20
>
> Maybe. (This was on "need a whole new type", not on "should be=20
> [preferably] taken by value or reference".) But, as you see from our=20
> discussion, how do you, personally, think, should I prepare the official=
=20
> proposal or the whole idea is doomed?=20
>
As I think about it, there has to be a better solution for this problem=20
than to create a mirror of all of the smart pointer types. After all, the=
=20
only difference between the pointer and reference versions is that the=20
reference will throw an exception if it is fed a NULL pointer value. And=20
what of people who use an intrusive_ptr class or something; they would have=
=20
to write their own intrusive_ref.
Maybe you could have some template class, smart_ref, which takes a=20
(presumably smart) pointer type. So you would have=20
smart_ref<shared_ptr<T>>. Of course, you can create typedefs for standard=
=20
smart pointers:
template<typename T> using shared_ref =3D smart_ref<shared_ptr<T>>;
template<typename T, typename D =3D std::default_delete<T>> using unique_re=
f=20
=3D smart_ref<unique_ptr<T, D>>;
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_45_1238907563.1425919599594
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, March 9, 2015 at 11:47:13 AM UTC-4, Pavel Kreto=
v wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> I think "object_p=
tr" is very much the wrong name. Why? A big part of the
<br>> problem is that the name obliterates the most important word in it=
s
<br>> predecessor: *shared*. What ownership semantics does "object_ptr" =
have:
<br>> shared, unique, none, something else? What would you name the "uni=
que_ptr"
<br>> analog to "object_ptr", or the "weak_ptr" equivalent? You'll still=
need
<br>> those to complete your interface (well, maybe not "weak_ptr"; that=
one you
<br>> can probably reuse).
<br>
<br>Maybe you're right. I was thinking a lot about choosing appropriate nam=
e=20
<br>for this entity. I started from "notnull_ptr", then thought of=20
<br>"shared_ref", but later decided it would be nice to employ term "object=
"=20
<br>in the meaning which I remember from reading C standard text:
<br>
<br> =C2=ABObject =E2=80=94 a region of data storage in =
the execution environment,
<br> the contents of which can represent values. Except=
for bit-fields,
<br> objects are composed of contiguous sequences of on=
e or more bytes,
<br> the number, order, and encoding of which are eithe=
r explicitly
<br> specified or implementation-defined.=C2=BB
<br>
<br>But to my surprise, when I've checked C++ 2014 draft I did not find thi=
s=20
<br>term. Name "shared_ref" seems to be appropriate for me, but we will be=
=20
<br>unable to make it behave like real reference as we cannot overload=20
<br>"operator.", it still will act like a pointer.
<br></blockquote><div><br>You use it like it's a pointer. But outside of ha=
ving to use ->, it will behave like a reference: it will always refer to=
an object.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> Pointers are how you refer to objects that might not be there. Referen=
ces
<br>> are how you refer to objects that *must* exist. Even though langua=
ge
<br>> references are not rebindable after creation, std::reference_wrapp=
er is. So
<br>> it's very much the same concept as what you want, only without the
<br>> ownership semantics.
<br>
<br>But without ownership semantics the whole proposal looses its meaning.
<br></blockquote><div><br>I meant that std::reference_wrapper has no owners=
hip semantics.<br><br>I also thought that std::reference_wrapper had an ope=
rator-> overload. It doesn't.<br><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">> The only way this class solves the problem is if the u=
ser is *always* using
<br>> it. If they used it from the moment they got that pointer, and pas=
sed it
<br>> along to you that way.
<br>> But shared_ptr beat you to it. It's already there, with lots of pe=
ople
<br>> using it for memory management. Not to mention the innumerable boo=
ks and
<br>> teaching materials beating "shared_ptr" into people's heads. Witho=
ut
<br>> widespread adoption of the type, the problem doesn't really get fi=
xed.
<br>
<br>You're freaking perfectly right. That is the sad part of story and the=
=20
<br>reason why I wrote my proposal into the mailing list associated with C+=
+=20
<br>standard committee instead of my Facebook page. :)
<br></blockquote><div><br>My point is that having the class and sticking it=
in a few interface functions doesn't fix the problem. It has to be used co=
nsistently and everywhere. And existing smart-pointers are already being wi=
dely used, so it's an uphill battle to get everyone to suddenly use another=
reference-counted object.<br><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;">> Well, you shouldn't be marking functions "noexcept" frequent=
ly to begin
<br>> with. But even if you want it to be noexcept, let it. noexcept doe=
sn't mean
<br>> "nothing gets thrown beyond this point". It means "if an exception=
gets
<br>> past me, kill the application." Therefore, the onus would be on th=
e
<br>> implementer of the function to catch any exceptions that he doesn'=
t want to
<br>> terminate the app.
<br>
<br>Thank you once again for your explanation. I liked the idea of throw=20
<br>lists a lot, given that that lists are to be checked by the compiler=20
<br>whether possible. "Noexcept" seems to be quite different. It seems I=20
<br>must read my C++ book once again.
<br></blockquote><div><br>No, it isn't. The same thing would happen in thro=
w lists too (assuming your compiler actually implemented them). If an excep=
tion other than a listed one tried to escape the function, then std::termin=
ate would be called.<br> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">
> The vast majority of parameters are (or should be) taken by value or b=
y
<br>> reference. By smart pointer is, compared to all parameters used in=
an API,
<br>> a relatively rare occurrence. Yes, it does happen. But it doesn't =
happen so
<br>> frequently that you need a whole new type to cover "by smart point=
er,
<br>> previously assured to not be NULL".
<br>
<br>Maybe. (This was on "need a whole new type", not on "should be=20
<br>[preferably] taken by value or reference".) But, as you see from our=20
<br>discussion, how do you, personally, think, should I prepare the officia=
l=20
<br>proposal or the whole idea is doomed?
<br></blockquote><div><br>As I think about it, there has to be a better sol=
ution for this problem than to create a mirror of all of the smart pointer =
types. After all, the only difference between the pointer and reference ver=
sions is that the reference will throw an exception if it is fed a NULL poi=
nter value. And what of people who use an intrusive_ptr class or something;=
they would have to write their own intrusive_ref.<br><br>Maybe you could h=
ave some template class, smart_ref, which takes a (presumably smart) pointe=
r type. So you would have smart_ref<shared_ptr<T>>. Of course, =
you can create typedefs for standard smart pointers:<br><br>template<typ=
ename T> using shared_ref =3D smart_ref<shared_ptr<T>>;<br>t=
emplate<typename T, typename D =3D std::default_delete<T>> usin=
g unique_ref =3D smart_ref<unique_ptr<T, D>>;<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_45_1238907563.1425919599594--
------=_Part_44_547709515.1425919599594--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Mon, 09 Mar 2015 13:58:58 -0400
Raw View
On 2015-03-09 11:46, Pavel Kretov wrote:
> I was thinking about proposing such a companion type for "uniq_ptr" too
> (I'm not sure about "weak_ptr"), but came to conclusion that "who would
> store null in uniq_ptr?".
FWIW... I would. I have an application with a number of optional
components. For obvious reasons, I don't want to have to think too hard
about memory management, so if the component is used, I want to store
the pointer in a std::unique_ptr, but if it is not used, I just leave
the std::unique_ptr default-initialized (i.e. null). Of course, that
would be similar to std::optional<std::unique_ref>.
(In the real application I think I'm using either QScopedPointer, which
is for all intents and purposes the Qt equivalent of std::unique_ptr, or
else relying on QObject hierarchies to reap the object, but the point
still stands.)
--
Matthew
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 09 Mar 2015 11:52:08 -0700
Raw View
On Monday 09 March 2015 17:45:09 Olaf van der Spek wrote:
> 2015-03-09 17:05 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> > On Monday 09 March 2015 15:59:19 Olaf van der Spek wrote:
> >> Do debuggers break if one calls terminate or abort?
> >
> > Yes, they usually do.
>
> $ ./a.out
> Aborted
>
> $ ./a.out
> terminate called without an active exception
> Aborted
>
> $ ./a.out
> a.out: b.cpp:6: int main(): Assertion `false' failed.
> Aborted
>
> I like the output of assert() better. Might be a toolchain issue though.
assert() is a macro, so it can record[*] the file name and line numbers of the
assertion. std::terminate() is a function, it can't do that.
If you want to get more information, run in the debugger and get the stack
trace.
[*] until you get customers asking you why their file names and function names
are leaking in the binary they created using your tools. See
https://codereview.qt-project.org/95627.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 9 Mar 2015 20:07:10 +0100
Raw View
2015-03-09 19:52 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> On Monday 09 March 2015 17:45:09 Olaf van der Spek wrote:
>> 2015-03-09 17:05 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
>> > On Monday 09 March 2015 15:59:19 Olaf van der Spek wrote:
>> >> Do debuggers break if one calls terminate or abort?
>> >
>> > Yes, they usually do.
>>
>> $ ./a.out
>> Aborted
>>
>> $ ./a.out
>> terminate called without an active exception
>> Aborted
>>
>> $ ./a.out
>> a.out: b.cpp:6: int main(): Assertion `false' failed.
>> Aborted
>>
>> I like the output of assert() better. Might be a toolchain issue though.
>
> assert() is a macro, so it can record[*] the file name and line numbers of the
> assertion. std::terminate() is a function, it can't do that.
I'm sure some compiler magic can fix that.
> If you want to get more information, run in the debugger and get the stack
> trace.
Not so simple on hard to reproduce bugs.
> [*] until you get customers asking you why their file names and function names
> are leaking in the binary they created using your tools. See
> https://codereview.qt-project.org/95627.
Sure, but what's your point?
--
Olaf
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Marc Mutz <marc.mutz@kdab.com>
Date: Mon, 9 Mar 2015 20:23:25 +0100
Raw View
On Monday 09 March 2015 14:49:28 Nicol Bolas wrote:
> That already exists; it's called a *reference*.
Yes, yes, the expected knee-jerk reaction... :)
"We don't need a Speed class", said the NASA engineer, "because that already
exists: it's called a *double*."
So tell me: since when can references be re-seated?
A reference is *not* a non-nullable pointer.
As for ownership: One could specialise nonnull_ptr for unique_ptr and
shared_ptr. Or have a nonnull template that can be specialised for other
types, too. It would be a big step in the direction of type-rich interfaces.
Thanks,
Marc
--
Marc Mutz <marc.mutz@kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-Independent Software Solutions
.
Author: Cleiton Santoia <cleitonsantoia@gmail.com>
Date: Mon, 9 Mar 2015 14:27:24 -0700 (PDT)
Raw View
------=_Part_870_405932278.1425936444959
Content-Type: multipart/alternative;
boundary="----=_Part_871_2095733474.1425936444959"
------=_Part_871_2095733474.1425936444959
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I understand the point "avoid id to receive a nullptr in a function" (=20
therefore not need to check )
int foo(const object_ptr<int>& i) {
return (int)i * 2; // nice boy, does not need to check !
}
however, I have a few doubts:
object_ptr<int> caller(int *p, std::shared<int> sp) {
int *a =3D new int(1);
int b =3D 2;
foo(a); // should be ok ( even when a is a local )
foo(&b); // should be ok ( even when b is a local )
// doubts:
foo(p); // doubt 1 : should check for p=3D=3Dnullptr, if true, then what=
?=20
throw an exception ? build a default int ?
foo(b); // doubt 2 : this is possible ? since ( b is not a pointer )
foo(3); // doubt 3 : this is possible ? since 3 is an int const and foo=
=20
parm also a const;
foo(sp); // doubt 4 : should check for sp=3D=3Dnullptr, if true, then wha=
t ?=20
throw an exception ? build a default int ?
return &b; // doubt 5 : what happen here ? since b is local.
}
BR
Cleiton
Em domingo, 8 de mar=C3=A7o de 2015 04:24:45 UTC-3, Pavel Kretov escreveu:
>
> Hello everybody.=20
>
> The problem I want you to discuss may have been already reviewed here,=20
> but I did not found anything similar in the mailing list archive. I was=
=20
> trying to explain the idea as well as I could, but I'm not a native=20
> speaker, so I might fail at some points. Excuse me for that.=20
>
> Have an nice weekend,=20
> =E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.=20
>
>
> =3D=3D=3D The problem =3D=3D=3D=20
>
> This is a common practice in programming to check input parameters for=20
> functions. As many parameters are pointers, smart or regular, checking=20
> them against "nullptr" is a *very* frequent operation, but what should=20
> you do if pointer is null? There are many options:=20
>
> =E2=80=94 silently return from the function?=20
> =E2=80=94 print warning message and return?=20
> =E2=80=94 throw an exception?=20
> =E2=80=94 call abort() from <cstdlib>?=20
> =E2=80=94 use some kind of ASSERT() and hope it will do the right thing=
?=20
> =E2=80=94 skip the check altogether and get a segfault in case?=20
>
> The exact choice may be different for different projects but each has=20
> its own drawbacks.=20
>
> =E2=80=94 If you chose to silently return, can you be sure that this is=
safe=20
> for the caller to stay unaware? Missing required parameter is a=20
> programmer's mistake and they should be told of it as soon as=20
> possible.=20
>
> =E2=80=94 If you chose to throw an exception, which one would you throw=
? Unlike=20
> languages like Java, C# or Python, C++ has a relatively poor set of=
=20
> predefined exceptions. It is also considered to be a good practice=20
> in C++ to trow and exception only in case of really exceptional=20
> situations and a single null pointer does not seem to be that much=20
> serious matter. Moreover, when choosing exceptions you will have to=
=20
> either pollute your functions' throw lists with std::invalid_argument=
=20
> or just omit them entirely. The latter means it is easy for your code=
=20
> user to forget to catch exceptions at all.=20
>
> =E2=80=94 Calling abort(), directly or as result of ASSERT, is no bette=
r then=20
> silently ignoring the error. I'm pretty sure nobody wants their=20
> enterprise level system to shut down without even syncing disk cache=
=20
> and database transactions due to forgotten null pointer passed to=20
> logger function.=20
>
> =E2=80=94 Ditto for not checking arguments at all.=20
>
>
> =3D=3D=3D The proposed solution =3D=3D=3D=20
>
> The problem could be completely eliminated in many cases if pointers=20
> were not allowed to carry invalid values at all. These days C++ has a=20
> strong movement toward smart pointers, leaving plain C pointers as a=20
> legacy option or for very low-level things. Classes std::shared_ptr and=
=20
> std::weak_ptr are commonly seen as a replacement.=20
>
> Shared pointers are designed to mimic the behavior of plain pointers,=20
> they can wrap any pointer, even the one which is not safe to deallocate=
=20
> using "delete" operator. It offers its user a great number of ways to=20
> misuse it.=20
>
> I propose to create a subclass of shared pointers, which is somewhat=20
> guaranteed to hold a valid object which can be safely deallocated. This=
=20
> class should:=20
>
> =E2=80=94 be unable to hold nullptr;=20
> =E2=80=94 have no conversion constructors from plain pointers;=20
> =E2=80=94 have object allocation to be the only way for pointer to be o=
btained.=20
>
> Lets call this class an std::object_ptr, after the term "object" which=20
> is used throughout C++ standard text, and declare it like the following:=
=20
>
> template <typename T>=20
> class object_ptr: public std::shared_ptr<T> {=20
> + only copy and move constructors;=20
> + all operators applicable to std::shared_ptr<T>;=20
> }=20
>
> template <typename T, typename TAlloc, typename... TArgs>=20
> object_ptr<T> allocate_object(const TAlloc& a, TArgs&&... args);=20
>
> template <typename T, typename... TArgs>=20
> object_ptr<T> make_object(TArgs&&... args);=20
>
> The instance of the class must also be convertible to a shared pointer=20
> which is never empty or null.=20
>
> After the class is introduced, you may simply write your functions=20
> arguments as std::object_ptr<T> if you expect them to be pointers to=20
> valid objects only and just skip any further null-pointer validation, or=
=20
> leave them as std::shared_ptr<T> in cases there nullability makes sense.=
=20
> Or better use std::object_ptr together with std::optional, like the=20
> following:=20
>
> void Scene::paintSprite(const object_ptr<Sprite>&);=20
>
> std::optional<std::shared_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> In the example above it is clear from the very declaration that painting=
=20
> null sprite is not allowed (as being pointless) while function=20
> "findSpline" can return sprite if it is able to find one, or can return=
=20
> nothing otherwise.=20
>
> We should also provide a way to create std::object_ptr from=20
> std::shared_ptr or even plain pointers for legacy purposes, but there=20
> should be the only one point there such a conversion is allowed. I'm not=
=20
> quite sure about the exact name and signature, but it should be a single=
=20
> function like that:=20
>
> template <typename T>=20
> std::object_ptr<T> object_ptr_cast(const std::shared_ptr<T>&)=20
> throw(std::invalid_argument);=20
>
> =3D=3D=3D Conclusion =3D=3D=3D=20
>
> Eliminating null pointers validation may seem to be not that big deal to=
=20
> create a special pointer type for that, but indeed it is a great=20
> problem: thousands of people around the world, writing programs in=20
> various languages, every day performs a lot of useless checks against=20
> NULL, just to throw an exception which in most cases will never be=20
> caught. We must do something to left those legacy checks behind and thus=
=20
> improve code readability and "self-documentability".=20
>
> To improve the situation, Java has introduced @NonNull arguments=20
> attribute years ago (which is anyway broken), Scala uses the Optional[T]=
=20
> pattern (as many other functional languages). There are languages like=20
> Kotlin, which sees "T" as non-nulable reference by default and require=20
> user to explicitly declare nullable references like "T?". (Moreover,=20
> Kotlin can check arguments during compilation, with respect to code path=
=20
> branching.) I think this approach will be widely adopted in the future=20
> programming languages and C++ must take some steps in this direction.=20
>
>
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_871_2095733474.1425936444959
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><br></div><div>I understand the point "avoid id to re=
ceive a nullptr in a function" ( therefore not need to check )</div><div><b=
r></div><div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187,=
187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><font color=3D"#66=
0066"><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> object_ptr</span><span style=3D"color=
: #080;" class=3D"styled-by-prettify"><int></span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</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> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">return</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: #008;" class=3D"styled-by-prettify">int</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">i </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"sty=
led-by-prettify">2</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: #800;" class=3D"styled-by-prettify">// n=
ice boy, does not need to check !</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span></font></div></code></div><div><br></div>however,=
I have a few doubts:</div><div><br></div><div><div class=3D"prettyprint" s=
tyle=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgr=
ound-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><font color=3D"#660066"><span style=3D"color: #000;" class=
=3D"styled-by-prettify">object_ptr</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><int></span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">caller</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">p</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">shared</span><span style=3D"color: #080;" class=3D"sty=
led-by-prettify"><int></span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> sp</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"styled-by-prettify">{</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></fon=
t><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">a </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">new</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> b </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><font color=3D"#006666"><span style=3D"color: #066;" =
class=3D"styled-by-prettify">2</span></font><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br><br> foo</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><font color=3D"#006666"><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">a</span></font><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: #800;" c=
lass=3D"styled-by-prettify">// should be ok ( even when a is a local )</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> foo<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(&</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">b</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #8=
00;" class=3D"styled-by-prettify">// should be ok </span><span style=3D"col=
or: rgb(136, 0, 0);"><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">( even when b is a local )</span></span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br><br></span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// doubts:</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> foo</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">p</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
// doubt 1 : should check for p=3D=3Dnullptr, if true, then what ? throw an=
exception ? build a default int </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">?</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> foo</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">b</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: #800;" class=3D"styled-by-prettify">// doubt 2=
: this is possible ? since ( b is not a pointer )</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br> foo</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><font color=3D"#006666"=
><span style=3D"color: #066;" class=3D"styled-by-prettify">3</span></font><=
span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// doubt 3 : </span><span st=
yle=3D"color: rgb(136, 0, 0);"><span style=3D"color: #800;" class=3D"styled=
-by-prettify">this is possible ? since 3 is an int const and foo parm also =
a const;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sp</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><span st=
yle=3D"color: #800;" class=3D"styled-by-prettify">// doubt 4 : </span><span=
style=3D"color: rgb(136, 0, 0);"><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">should check for sp=3D=3Dnullptr, if true, then what ? thr=
ow an exception ? build a default int ?</span></span><span style=3D"color: =
rgb(136, 0, 0);"><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span></span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">return</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">b</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800=
;" class=3D"styled-by-prettify">// doubt 5 : what happen here ? since b is =
local.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</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></div></=
code></div></div><div><br></div><div>BR</div><div>Cleiton</div><div><br>Em =
domingo, 8 de mar=C3=A7o de 2015 04:24:45 UTC-3, Pavel Kretov escreveu:<bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;">Hello everybody.
<br>
<br>The problem I want you to discuss may have been already reviewed here,=
=20
<br>but I did not found anything similar in the mailing list archive. I was=
=20
<br>trying to explain the idea as well as I could, but I'm not a native=20
<br>speaker, so I might fail at some points. Excuse me for that.
<br>
<br>Have an nice weekend,
<br>=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
<br>
<br>
<br>=3D=3D=3D The problem =3D=3D=3D
<br>
<br>This is a common practice in programming to check input parameters for
<br>functions. As many parameters are pointers, smart or regular, checking
<br>them against "nullptr" is a *very* frequent operation, but what should=
=20
<br>you do if pointer is null? There are many options:
<br>
<br> =E2=80=94 silently return from the function?
<br> =E2=80=94 print warning message and return?
<br> =E2=80=94 throw an exception?
<br> =E2=80=94 call abort() from <cstdlib>?
<br> =E2=80=94 use some kind of ASSERT() and hope it will do the righ=
t thing?
<br> =E2=80=94 skip the check altogether and get a segfault in case?
<br>
<br>The exact choice may be different for different projects but each has=
=20
<br>its own drawbacks.
<br>
<br> =E2=80=94 If you chose to silently return, can you be sure that =
this is safe
<br> for the caller to stay unaware? Missing required paramete=
r is a
<br> programmer's mistake and they should be told of it as soo=
n as
<br> possible.
<br>
<br> =E2=80=94 If you chose to throw an exception, which one would yo=
u throw? Unlike
<br> languages like Java, C# or Python, C++ has a relatively p=
oor set of
<br> predefined exceptions. It is also considered to be a good=
practice
<br> in C++ to trow and exception only in case of really excep=
tional
<br> situations and a single null pointer does not seem to be =
that much
<br> serious matter. Moreover, when choosing exceptions you wi=
ll have to
<br> either pollute your functions' throw lists with std::inva=
lid_argument
<br> or just omit them entirely. The latter means it is easy f=
or your code
<br> user to forget to catch exceptions at all.
<br>
<br> =E2=80=94 Calling abort(), directly or as result of ASSERT, is n=
o better then
<br> silently ignoring the error. I'm pretty sure nobody wants=
their
<br> enterprise level system to shut down without even syncing=
disk cache
<br> and database transactions due to forgotten null pointer p=
assed to
<br> logger function.
<br>
<br> =E2=80=94 Ditto for not checking arguments at all.
<br>
<br>
<br>=3D=3D=3D The proposed solution =3D=3D=3D
<br>
<br>The problem could be completely eliminated in many cases if pointers=20
<br>were not allowed to carry invalid values at all. These days C++ has a=
=20
<br>strong movement toward smart pointers, leaving plain C pointers as a=20
<br>legacy option or for very low-level things. Classes std::shared_ptr and=
=20
<br>std::weak_ptr are commonly seen as a replacement.
<br>
<br>Shared pointers are designed to mimic the behavior of plain pointers,=
=20
<br>they can wrap any pointer, even the one which is not safe to deallocate=
=20
<br>using "delete" operator. It offers its user a great number of ways to=
=20
<br>misuse it.
<br>
<br>I propose to create a subclass of shared pointers, which is somewhat=20
<br>guaranteed to hold a valid object which can be safely deallocated. This=
=20
<br>class should:
<br>
<br> =E2=80=94 be unable to hold nullptr;
<br> =E2=80=94 have no conversion constructors from plain pointers;
<br> =E2=80=94 have object allocation to be the only way for pointer =
to be obtained.
<br>
<br>Lets call this class an std::object_ptr, after the term "object" which=
=20
<br>is used throughout C++ standard text, and declare it like the following=
:
<br>
<br> template <typename T>
<br> class object_ptr: public std::shared_ptr<T> {
<br> + only copy and move constructors;
<br> + all operators applicable to std::sh=
ared_ptr<T>;
<br> }
<br>
<br> template <typename T, typename TAlloc, typename.=
... TArgs>
<br> object_ptr<T> allocate_object(const TAlloc&am=
p; a, TArgs&&... args);
<br>
<br> template <typename T, typename... TArgs>
<br> object_ptr<T> make_object(TArgs&&... =
args);
<br>
<br>The instance of the class must also be convertible to a shared pointer=
=20
<br>which is never empty or null.
<br>
<br>After the class is introduced, you may simply write your functions=20
<br>arguments as std::object_ptr<T> if you expect them to be pointers=
to=20
<br>valid objects only and just skip any further null-pointer validation, o=
r=20
<br>leave them as std::shared_ptr<T> in cases there nullability makes=
sense.=20
<br>Or better use std::object_ptr together with std::optional, like the=20
<br>following:
<br>
<br> void Scene::paintSprite(const object_ptr<Sprite&=
gt;&);
<br>
<br> std::optional<std::shared_<wbr>ptr<Sprite>=
>
<br> Scene::findSprite(const Point&);
<br>
<br>In the example above it is clear from the very declaration that paintin=
g=20
<br>null sprite is not allowed (as being pointless) while function=20
<br>"findSpline" can return sprite if it is able to find one, or can return=
=20
<br>nothing otherwise.
<br>
<br>We should also provide a way to create std::object_ptr from=20
<br>std::shared_ptr or even plain pointers for legacy purposes, but there=
=20
<br>should be the only one point there such a conversion is allowed. I'm no=
t=20
<br>quite sure about the exact name and signature, but it should be a singl=
e=20
<br>function like that:
<br>
<br> template <typename T>
<br> std::object_ptr<T> object_ptr_cast(const std:=
:shared_ptr<T>&)
<br> &=
nbsp; throw(s=
td::invalid_argument);
<br>
<br>=3D=3D=3D Conclusion =3D=3D=3D
<br>
<br>Eliminating null pointers validation may seem to be not that big deal t=
o=20
<br>create a special pointer type for that, but indeed it is a great=20
<br>problem: thousands of people around the world, writing programs in=20
<br>various languages, every day performs a lot of useless checks against=
=20
<br>NULL, just to throw an exception which in most cases will never be=20
<br>caught. We must do something to left those legacy checks behind and thu=
s=20
<br>improve code readability and "self-documentability".
<br>
<br>To improve the situation, Java has introduced @NonNull arguments=20
<br>attribute years ago (which is anyway broken), Scala uses the Optional[T=
]=20
<br>pattern (as many other functional languages). There are languages like=
=20
<br>Kotlin, which sees "T" as non-nulable reference by default and require=
=20
<br>user to explicitly declare nullable references like "T?". (Moreover,=20
<br>Kotlin can check arguments during compilation, with respect to code pat=
h=20
<br>branching.) I think this approach will be widely adopted in the future=
=20
<br>programming languages and C++ must take some steps in this direction.
<br>
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_871_2095733474.1425936444959--
------=_Part_870_405932278.1425936444959--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 9 Mar 2015 16:09:05 -0700 (PDT)
Raw View
------=_Part_1209_652040735.1425942545906
Content-Type: multipart/alternative;
boundary="----=_Part_1210_239582504.1425942545906"
------=_Part_1210_239582504.1425942545906
Content-Type: text/plain; charset=UTF-8
On Monday, March 9, 2015 at 3:18:33 PM UTC-4, Marc Mutz wrote:
>
> On Monday 09 March 2015 14:49:28 Nicol Bolas wrote:
> > That already exists; it's called a *reference*.
>
> Yes, yes, the expected knee-jerk reaction... :)
>
Yes; the right answer often is predictable.
"We don't need a Speed class", said the NASA engineer, "because that
> already
> exists: it's called a *double*."
>
I'm fairly sure they don't have a Speed class now either.
> So tell me: since when can references be re-seated?
>
> A reference is *not* a non-nullable pointer.
>
auto foo = std::ref(bar);
foo = std::ref(blah);
References look pretty reseatable to me. Unless you're saying that
std::reference_wrapper is poorly named?
The fact that language references can't be reseated doesn't change the fact
that reference semantics are functionally identical to non-nullable
pointers.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1210_239582504.1425942545906
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, March 9, 2015 at 3:18:33 PM UTC-4, Marc Mutz wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday 09 March 2015 14=
:49:28 Nicol Bolas wrote:
<br>> That already exists; it's called a *reference*.
<br>
<br>Yes, yes, the expected knee-jerk reaction... :)
<br></blockquote><div><br>Yes; the right answer often is predictable.<br><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
"We don't need a Speed class", said the NASA engineer, "because that alread=
y=20
<br>exists: it's called a *double*."
<br></blockquote><div><br>I'm fairly sure they don't have a Speed class now=
either.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
So tell me: since when can references be re-seated?
<br>
<br>A reference is *not* a non-nullable pointer.<br></blockquote><div><br>a=
uto foo =3D std::ref(bar);<br>foo =3D std::ref(blah);<br><br>References loo=
k pretty reseatable to me. Unless you're saying that std::reference_wrapper=
is poorly named?<br><br>The fact that language references can't be reseate=
d doesn't change the fact that reference semantics are functionally identic=
al to non-nullable pointers.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1210_239582504.1425942545906--
------=_Part_1209_652040735.1425942545906--
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Tue, 10 Mar 2015 13:48:59 +0300
Raw View
>> "We don't need a Speed class", said the NASA engineer, "because that
>> already exists: it's called a *double*."
>
> I'm fairly sure they don't have a Speed class now either.
Maybe they use boost::units, as the idea to explicitly assign units to=20
quantities seems to be perfectly suitable for rocket science. Or maybe=20
they have already developed their own version of C++ for that, who knows.
=E2=80=94=E2=80=94=E2=80=94 P. K.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Tue, 10 Mar 2015 14:14:56 +0300
Raw View
>>>> I don't consider regular pointers as
>>>> I believe that future programs will use them exceptionally rare.
>>>
>>> I think you're wrong. Regular pointers are fine as long as they don't o=
wn
>>> the pointee.
>>
>> Regular pointers are fine when used appropriately. But they don't seem
>> appropriate for me in cases where their use would lead to a bunch of
>> ownership semantics problems. I'm not a foreteller, but I can see the
>> movement toward using smart pointers in C++ community.
>
> That does not contradict my statement.
Okay, I'll try to say another way. I think that the number if places,=20
where you cannot use references, but can use pointers without worrying=20
about ownership, are rare. But anyway, there is no point in arguing as=20
we're talking about the future.
>> Not always. You would probably want to do something to recover your prog=
ram
>> from every possible and impossible error if that program is leading the
>> rocket to an orbit. (Quite edgy example, though.)
>
> I don't know, I'm not a rocket scientist. Are you?
> Exception and dynamic memory are probably forbidden in those cases anyway=
...
I'm not the rocket one, what is why I called the example "edgy".=20
Probably they forbid dynamic memory and exceptions (I'm pretty sure,=20
indeed), but what I know is that for writing responsible systems many=20
rules are often enforced as a convention ("We do not use exceptions in=20
rocket control module, return -1 instead"), but who said that none of=20
them are old or even plain wrong. Moreover, conventions are bad when=20
they're not automatically enforced.
> Rockets might self-destruct or call a fatal error handler too, I don't
> think they try to somehow ignore the error.
In the worst case they could launch a missile and take the rocket down.=20
But not due to null pointer exception, I hope.
>> You cannot simply assign non-nullable pointer a value, but if you try to
>> construct one with from a null, you would get an exception. But if your
>> program uses non-nullable pointers wherever possible, you would need to
>> control this exception very rarely.
>
> IMO the same is true for using normal smart pointers and normal
> references. Issues with null pointers just don't come up often.
It depends. To my experience, when the system is decoupled into many=20
simple classes, almost every class has at least one pointer parameter in=20
one of its interface methods.
=E2=80=94=E2=80=94=E2=80=94 P. K.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 10 Mar 2015 08:46:06 -0700
Raw View
On Monday 09 March 2015 20:07:10 Olaf van der Spek wrote:
> > [*] until you get customers asking you why their file names and function
> > names are leaking in the binary they created using your tools. See
> > https://codereview.qt-project.org/95627.
>
> Sure, but what's your point?
Just that file names and line numbers are overrated and you may not want to
have them at all assertion & termination points, since that may leak
information you don't want other people to have.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Tue, 10 Mar 2015 19:50:18 +0100
Raw View
2015-03-10 16:46 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> On Monday 09 March 2015 20:07:10 Olaf van der Spek wrote:
>> > [*] until you get customers asking you why their file names and function
>> > names are leaking in the binary they created using your tools. See
>> > https://codereview.qt-project.org/95627.
>>
>> Sure, but what's your point?
>
> Just that file names and line numbers are overrated and you may not want to
> have them at all assertion & termination points, since that may leak
> information you don't want other people to have.
Sure, putting file/function names and line numbers into a (release)
executable might not be the smartest thing, but maybe it's exactly
what you want.
--
Olaf
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Tue, 10 Mar 2015 22:06:10 +0300
Raw View
> Just that file names and line numbers are overrated and you may not want =
to
> have them at all assertion & termination points, since that may leak
> information you don't want other people to have.
What is so secret about file names? (Apart from revealing to the world=20
the fact that you, for example, is actually linking GPLed library into=20
your proprietary application?) File names are just file names.
=E2=80=94=E2=80=94=E2=80=94 P. K.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Tue, 10 Mar 2015 13:31:37 -0700 (PDT)
Raw View
------=_Part_6_1838582577.1426019497040
Content-Type: multipart/alternative;
boundary="----=_Part_7_915174956.1426019497040"
------=_Part_7_915174956.1426019497040
Content-Type: text/plain; charset=UTF-8
They may save you some time when doing reverse engineering.
It gives you some context.
On Tuesday, March 10, 2015 at 4:06:15 PM UTC-3, Pavel Kretov wrote:
>
> What is so secret about file names? (Apart from revealing to the world
> the fact that you, for example, is actually linking GPLed library into
> your proprietary application?) File names are just file names.
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7_915174956.1426019497040
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">They may save you some time when doing reverse engineering=
..<br>It gives you some context.<br><br>On Tuesday, March 10, 2015 at 4:06:1=
5 PM UTC-3, Pavel Kretov wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
>What is so secret about file names? (Apart from revealing to the world=20
<br>the fact that you, for example, is actually linking GPLed library into=
=20
<br>your proprietary application?) File names are just file names.
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7_915174956.1426019497040--
------=_Part_6_1838582577.1426019497040--
.
Author: Cleiton Santoia <cleitonsantoia@gmail.com>
Date: Thu, 12 Mar 2015 14:24:54 -0700 (PDT)
Raw View
------=_Part_4_1285103047.1426195494456
Content-Type: multipart/alternative;
boundary="----=_Part_5_1483873050.1426195494456"
------=_Part_5_1483873050.1426195494456
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Mr Kretov, I agree with Thiago,
I think that is really important be able to NOT pass this information if=20
you don't wan to,=20
but I=C2=B4m traversing the conversation just to say that yet have to answe=
r my=20
previous questions please :)
Cleiton
Em ter=C3=A7a-feira, 10 de mar=C3=A7o de 2015 16:06:15 UTC-3, Pavel Kretov =
escreveu:
>
> > Just that file names and line numbers are overrated and you may not wan=
t=20
> to=20
> > have them at all assertion & termination points, since that may leak=20
> > information you don't want other people to have.=20
>
> What is so secret about file names? (Apart from revealing to the world=20
> the fact that you, for example, is actually linking GPLed library into=20
> your proprietary application?) File names are just file names.=20
>
> =E2=80=94=E2=80=94=E2=80=94 P. K.=20
>
>
>
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_5_1483873050.1426195494456
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Mr Kretov, I agree with Thiago,<div><br></div><div>I think=
that is really important be able to NOT pass this information if you don't=
wan to, </div><div>but I=C2=B4m traversing the conversation just to s=
ay that yet have to answer my previous questions please :)<br></div><div><b=
r></div><div>Cleiton<br></div><div><br>Em ter=C3=A7a-feira, 10 de mar=C3=A7=
o de 2015 16:06:15 UTC-3, Pavel Kretov escreveu:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;">> Just that file names and line numbers are overrated=
and you may not want to
<br>> have them at all assertion & termination points, since that ma=
y leak
<br>> information you don't want other people to have.
<br>
<br>What is so secret about file names? (Apart from revealing to the world=
=20
<br>the fact that you, for example, is actually linking GPLed library into=
=20
<br>your proprietary application?) File names are just file names.
<br>
<br>=E2=80=94=E2=80=94=E2=80=94 P. K.
<br>
<br>
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5_1483873050.1426195494456--
------=_Part_4_1285103047.1426195494456--
.
Author: Pavel Kretov <firegurafiku@gmail.com>
Date: Fri, 13 Mar 2015 00:58:32 +0300
Raw View
> but I=C2=B4m traversing the conversation just to say that yet have to
> answer my previous questions please :)
Sorry, I've missed your letter a bit. I'm now thinking about what I'm
going to do with the proposal, prepare paper or not, and looked the list
not very carefully.
> however, I have a few doubts:
>
> object_ptr<int> caller(int *p, std::shared<int> sp) { int *a =3D new
> int(1); int b =3D 2;
>
> foo(a); // should be ok ( even when a is a local )
In fact, not okay. There is no way for "object_ptr" to know the fact
that "a" was obtained with "new" and thus cannot hold null. You should
write instead:
auto a =3D std::make_object<int>();
> foo(&b); // should be ok ( even when b is a local )
Also not okay, the same reason. But in that particular situation you
should use plain references (int&).
> foo(p); // doubt 1 : should check for p=3D=3Dnullptr, if true, then what=
?
> throw an exception? build a default int?
Also would not compile. "p" is a plain pointer which can possibly hold=20
null value, you have to explicitly obtain object_ptr from it:
foo(object_ptr(p));
which would throw and exception if the pointer is invalid.
> foo(b); // doubt 2 : this is possible ? since (b is not a pointer)
Would not compile, not implicit conversion from "int". In fact, you=20
really don't need that conversion to be implicit.
> foo(3); // doubt 3 : this is possible ? since 3 is an int const and
> foo
The same thing.
> foo(sp); // doubt 4 : should check for sp=3D=3Dnullptr, if true, then
> what ?
Would not compile. Nullable shared pointer must be explicitly converted=20
to non-nullable.
> throw an exception ? build a default int ?
Yes, it is supposed to throw an exception if this explicit conversion=20
detects null pointer.
> return &b; // doubt 5 : what happen here ? since b is local.
Would not compile as conversion is explicit. But if you insist on=20
foot-shooting, use "object_ptr(&b)", which will be runtime error.
In fact, looking at your questions, I started thinking that maybe my=20
proposal is wrong, as the language is already very freaking complex,=20
and, moreover, the very idea of smart pointers haven't yet been fully=20
accepted by many developers' minds.
=E2=80=94=E2=80=94=E2=80=94 P. K.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Cleiton Santoia <cleitonsantoia@gmail.com>
Date: Thu, 12 Mar 2015 15:30:36 -0700 (PDT)
Raw View
------=_Part_58_1113443884.1426199436541
Content-Type: multipart/alternative;
boundary="----=_Part_59_1552407701.1426199436548"
------=_Part_59_1552407701.1426199436548
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Don't worry I got some solution to this but was a too rubbish to propose.
Lately I use more and more a "sentinela(portuguese)", probably "sentry" in=
=20
english technique.
When you are implementing a double linked list, is better to spare two=20
allocations and build a dummy ( or sentry ) head and tail, so you never=20
point head and tail to nullptr and you never need to verify this in the=20
code.
So i came up with a=20
ensured_shared_ptr<T,deleter,dummy_nullptr_instance_allocator>
whenever you need to dereference a nullptr, the "ensured_shared_ptr"=20
ensures one valid to you, by allocating via=20
dummy_nullptr_instance_allocator, when you create a instance of T (probably=
=20
descendant of T) that only drop logs on each call and do some house keeping=
=20
enough to not break the system.
Clearly this has a lot of other problems, you get more instances that what=
=20
you need, sometimes is better to stop processing or throw an exception, and=
=20
not aways is possible to get a class T that will handle gracefully a dummy=
=20
value, but in some cases it=C2=B4s really beter;
Cleiton
Em quinta-feira, 12 de mar=C3=A7o de 2015 18:58:37 UTC-3, Pavel Kretov escr=
eveu:
>
> > but I=C2=B4m traversing the conversation just to say that yet have to=
=20
> > answer my previous questions please :)=20
>
> Sorry, I've missed your letter a bit. I'm now thinking about what I'm=20
> going to do with the proposal, prepare paper or not, and looked the list=
=20
> not very carefully.=20
>
> > however, I have a few doubts:=20
> >=20
> > object_ptr<int> caller(int *p, std::shared<int> sp) { int *a =3D new=20
> > int(1); int b =3D 2;=20
> >=20
> > foo(a); // should be ok ( even when a is a local )=20
>
> In fact, not okay. There is no way for "object_ptr" to know the fact=20
> that "a" was obtained with "new" and thus cannot hold null. You should=20
> write instead:=20
>
> auto a =3D std::make_object<int>();=20
>
> > foo(&b); // should be ok ( even when b is a local )=20
>
> Also not okay, the same reason. But in that particular situation you=20
> should use plain references (int&).=20
>
> > foo(p); // doubt 1 : should check for p=3D=3Dnullptr, if true, then wh=
at?=20
> > throw an exception? build a default int?=20
>
> Also would not compile. "p" is a plain pointer which can possibly hold=20
> null value, you have to explicitly obtain object_ptr from it:=20
>
> foo(object_ptr(p));=20
>
> which would throw and exception if the pointer is invalid.=20
>
> > foo(b); // doubt 2 : this is possible ? since (b is not a pointer)=20
>
> Would not compile, not implicit conversion from "int". In fact, you=20
> really don't need that conversion to be implicit.=20
>
> > foo(3); // doubt 3 : this is possible ? since 3 is an int const and=20
> > foo=20
>
> The same thing.=20
>
> > foo(sp); // doubt 4 : should check for sp=3D=3Dnullptr, if true, then=
=20
> > what ?=20
>
> Would not compile. Nullable shared pointer must be explicitly converted=
=20
> to non-nullable.=20
>
> > throw an exception ? build a default int ?=20
>
> Yes, it is supposed to throw an exception if this explicit conversion=20
> detects null pointer.=20
>
> > return &b; // doubt 5 : what happen here ? since b is local.=20
>
> Would not compile as conversion is explicit. But if you insist on=20
> foot-shooting, use "object_ptr(&b)", which will be runtime error.=20
>
> In fact, looking at your questions, I started thinking that maybe my=20
> proposal is wrong, as the language is already very freaking complex,=20
> and, moreover, the very idea of smart pointers haven't yet been fully=20
> accepted by many developers' minds.=20
>
> =E2=80=94=E2=80=94=E2=80=94 P. K.=20
>
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_59_1552407701.1426199436548
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Don't worry I got some solution to this but was a too rubb=
ish to propose.<div><br></div><div>Lately I use more and more a "sentinela(=
portuguese)", probably "sentry" in english technique.</div><div>When you ar=
e implementing a double linked list, is better to spare two allocations and=
build a dummy ( or sentry ) head and tail, so you never point head and tai=
l to nullptr and you never need to verify this in the code.</div><div><br><=
/div><div>So i came up with a </div><div><br></div><div><div class=3D"=
prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: brea=
k-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><font color=3D"#660066"><span style=3D"color:=
#000;" class=3D"styled-by-prettify">ensured_shared_ptr</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">deleter</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">dummy_nullptr_instance_allocator</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">></span></font></div></code></div><br>=
whenever you need to dereference a nullptr, the "ensured_shared_ptr" ensure=
s one valid to you, by allocating via dummy_nullptr_instance_allocator, whe=
n you create a instance of T (probably descendant of T) that only drop logs=
on each call and do some house keeping enough to not break the system.</di=
v><div><br></div><div>Clearly this has a lot of other problems, you get mor=
e instances that what you need, sometimes is better to stop processing or t=
hrow an exception, and not aways is possible to get a class T that will han=
dle gracefully a dummy value, but in some cases it=C2=B4s really beter;</di=
v><div><br></div><div>Cleiton</div><div><br><br>Em quinta-feira, 12 de mar=
=C3=A7o de 2015 18:58:37 UTC-3, Pavel Kretov escreveu:<blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">> but I=C2=B4m traversing the conversation just=
to say that yet have to
<br>> answer my previous questions please :)
<br>
<br>Sorry, I've missed your letter a bit. I'm now thinking about what I'm
<br>going to do with the proposal, prepare paper or not, and looked the lis=
t
<br>not very carefully.
<br>
<br>> however, I have a few doubts:
<br>>
<br>> object_ptr<int> caller(int *p, std::shared<int> sp) { =
int *a =3D new
<br>> int(1); int b =3D 2;
<br>>
<br>> foo(a); // should be ok ( even when a is a local )
<br>
<br>In fact, not okay. There is no way for "object_ptr" to know the fact
<br>that "a" was obtained with "new" and thus cannot hold null. You should
<br>write instead:
<br>
<br> auto a =3D std::make_object<int>();
<br>
<br>> foo(&b); // should be ok ( even when b is a local )
<br>
<br>Also not okay, the same reason. But in that particular situation you
<br>should use plain references (int&).
<br>
<br>> foo(p); // doubt 1 : should check for p=3D=3Dnullptr, if tru=
e, then what?
<br>> throw an exception? buil=
d a default int?
<br>
<br>Also would not compile. "p" is a plain pointer which can possibly hold=
=20
<br>null value, you have to explicitly obtain object_ptr from it:
<br>
<br> foo(object_ptr(p));
<br>
<br>which would throw and exception if the pointer is invalid.
<br>
<br>> foo(b); // doubt 2 : this is possible ? since (b is not a po=
inter)
<br>
<br>Would not compile, not implicit conversion from "int". In fact, you=20
<br>really don't need that conversion to be implicit.
<br>
<br>> foo(3); // doubt 3 : this is possible ? since 3 is an int co=
nst and
<br>> foo
<br>
<br>The same thing.
<br>
<br>> foo(sp); // doubt 4 : should check for sp=3D=3Dnullptr, if true, t=
hen
<br>> what ?
<br>
<br>Would not compile. Nullable shared pointer must be explicitly converted=
=20
<br>to non-nullable.
<br>
<br>> throw an exception ? build a default int ?
<br>
<br>Yes, it is supposed to throw an exception if this explicit conversion=
=20
<br>detects null pointer.
<br>
<br>> return &b; // doubt 5 : what happen here ? since b is local.
<br>
<br>Would not compile as conversion is explicit. But if you insist on=20
<br>foot-shooting, use "object_ptr(&b)", which will be runtime error.
<br>
<br>In fact, looking at your questions, I started thinking that maybe my=20
<br>proposal is wrong, as the language is already very freaking complex,=20
<br>and, moreover, the very idea of smart pointers haven't yet been fully=
=20
<br>accepted by many developers' minds.
<br>
<br>=E2=80=94=E2=80=94=E2=80=94 P. K.
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_59_1552407701.1426199436548--
------=_Part_58_1113443884.1426199436541--
.
Author: Marc Mutz <marc.mutz@kdab.com>
Date: Tue, 17 Mar 2015 10:35:50 +0100
Raw View
On Tuesday 10 March 2015 00:09:05 Nicol Bolas wrote:
> > So tell me: since when can references be re-seated?
> >
> > A reference is not a non-nullable pointer.
>
> auto foo = std::ref(bar);
> foo = std::ref(blah);
>
> References look pretty reseatable to me. Unless you're saying that
> std::reference_wrapper is poorly named?
>
> The fact that language references can't be reseated doesn't change the
> fact that reference semantics are functionally identical to non-nullable
> pointers.
std::reference_wrapper is a _reference_ wrapper. It doesn't model a _pointer_.
I'm looking for a way to say clearly and unambiguously that a function expects
a non-null pointer. std::reference_wrapper doesn't fit the bill, for at least
two reasons: Use of it in APIs is surprising absent any text book (that I know
of) introducing it as a pattern for a non-null pointer. Even if that was a
pattern, it would suffer from the ambiguity that there might be other valid
reasons to accept a reference_wrapper in the API[1]. non_nullptr<T> says
exactly and unambiguously that the argument is a non-null pointer. You
wouldn't use a Point2D to represent Size2D even if both (and std::complex) are
layout-compatible to pair<T, T>.
For a concrete example: how would std:.reference_wrapper help with expressing
the requirement that std::basic_string(const CharT*) requires a non-null
argument?
Thanks,
Marc
[1] e.g. std::begin() could do with one, so you could force range-for to use
const_iterator by saying for (i: cref(vec)) - that's important for (broken)
designs in which containers are COW.
--
Marc Mutz <marc.mutz@kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 17 Mar 2015 10:38 -0700
Raw View
On Tuesday 17 March 2015 10:35:50 Marc Mutz wrote:
> For a concrete example: how would std:.reference_wrapper help with
> expressing the requirement that std::basic_string(const CharT*) requires a
> non-null argument?
Non-example if we had used reference_wrapper:
std::string foo(*"some text");
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 17 Mar 2015 13:03:28 -0500
Raw View
--001a1139cb5e130b8905117fcbd4
Content-Type: text/plain; charset=UTF-8
On 17 March 2015 at 04:35, Marc Mutz <marc.mutz@kdab.com> wrote:
> For a concrete example: how would std:.reference_wrapper help with
> expressing
> the requirement that std::basic_string(const CharT*) requires a non-null
> argument?
>
That isn't the requirement. From N4296
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf>
[string.cons]
p8:
Requires: s points to an array of at least traits::length(s) + 1 elements
of charT.
How are you going to model that in the type system? Just modeling
non-nullable pointer is just a half-measure.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1139cb5e130b8905117fcbd4
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 17 March 2015 at 04:35, Marc Mutz <span dir=3D"ltr"><=
;<a href=3D"mailto:marc.mutz@kdab.com" target=3D"_blank">marc.mutz@kdab.com=
</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex">For a concrete example: how would std:.reference_wrap=
per help with expressing<br>
the requirement that std::basic_string(const CharT*) requires a non-null<br=
>
argument?<br></blockquote><div><br></div><div>That isn't the requiremen=
t.=C2=A0 From=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/p=
apers/2014/n4296.pdf">N4296</a>=C2=A0[string.cons] p8:</div><div><br></div>=
<div><p style=3D"margin:0px;font-size:10px;font-family:Helvetica">=C2=A0Req=
uires: s points to an array of at least traits::length(s) + 1 elements of c=
harT.</p></div><div><br></div><div>=C2=A0How are you going to model that in=
the type system?=C2=A0 Just modeling non-nullable pointer is just a half-m=
easure.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin "=
:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" =
target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1139cb5e130b8905117fcbd4--
.
Author: Marc Mutz <marc.mutz@kdab.com>
Date: Tue, 17 Mar 2015 21:05:30 +0100
Raw View
On Tuesday 17 March 2015 19:03:28 Nevin Liber wrote:
> On 17 March 2015 at 04:35, Marc Mutz <marc.mutz@kdab.com> wrote:
> > For a concrete example: how would std:.reference_wrapper help with
> > expressing
> > the requirement that std::basic_string(const CharT*) requires a non-null
> > argument?
>
> That isn't the requirement.
*shrug*
Sure it's not _the whole_ requirements, but a necessary subset. And it's
usually the case that the type system only checks for a necessary subset of a
function's preconditions.
> How are you going to model that in the type system? Just modeling
> non-nullable pointer is just a half-measure.
Just because in general you cannot check all preconditions statically doesn't
mean you shouldn't check the necessary subset that can be represented in the
type system. E.g. you often require that a non-null pointer, points to a valid
object. But that's usually implied for non-void*/char*s.
And when your function accepts some form of Speed type, you will also usually
require that the value isn't nan, or infinity.
This stuff doesn't have to be perfect. Just better is enough.
Thanks,
Marc
--
Marc Mutz <marc.mutz@kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
.
Author: georgesovetov@gmail.com
Date: Sat, 21 Nov 2015 02:24:48 -0800 (PST)
Raw View
------=_Part_2397_464074427.1448101489019
Content-Type: multipart/alternative;
boundary="----=_Part_2398_1630773898.1448101489019"
------=_Part_2398_1630773898.1448101489019
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I completely support this idea and its concept may even become part of my=
=20
scientific work. The only problem is to find appropriate, meaningful,=20
consistent names for non-nullable pointers.
Nulls (None's, nil's) are headache in C++, C#, Java, Python, Objective C=20
and so on.
Contract should be as explicit as possible. The earlier arguments are=20
checked the less harmful potential consequences are.
On Sunday, March 8, 2015 at 10:24:45 AM UTC+3, Pavel Kretov wrote:
>
> Hello everybody.=20
>
> The problem I want you to discuss may have been already reviewed here,=20
> but I did not found anything similar in the mailing list archive. I was=
=20
> trying to explain the idea as well as I could, but I'm not a native=20
> speaker, so I might fail at some points. Excuse me for that.=20
>
> Have an nice weekend,=20
> =E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.=20
>
>
> =3D=3D=3D The problem =3D=3D=3D=20
>
> This is a common practice in programming to check input parameters for=20
> functions. As many parameters are pointers, smart or regular, checking=20
> them against "nullptr" is a *very* frequent operation, but what should=20
> you do if pointer is null? There are many options:=20
>
> =E2=80=94 silently return from the function?=20
> =E2=80=94 print warning message and return?=20
> =E2=80=94 throw an exception?=20
> =E2=80=94 call abort() from <cstdlib>?=20
> =E2=80=94 use some kind of ASSERT() and hope it will do the right thing=
?=20
> =E2=80=94 skip the check altogether and get a segfault in case?=20
>
> The exact choice may be different for different projects but each has=20
> its own drawbacks.=20
>
> =E2=80=94 If you chose to silently return, can you be sure that this is=
safe=20
> for the caller to stay unaware? Missing required parameter is a=20
> programmer's mistake and they should be told of it as soon as=20
> possible.=20
>
> =E2=80=94 If you chose to throw an exception, which one would you throw=
? Unlike=20
> languages like Java, C# or Python, C++ has a relatively poor set of=
=20
> predefined exceptions. It is also considered to be a good practice=20
> in C++ to trow and exception only in case of really exceptional=20
> situations and a single null pointer does not seem to be that much=20
> serious matter. Moreover, when choosing exceptions you will have to=
=20
> either pollute your functions' throw lists with std::invalid_argument=
=20
> or just omit them entirely. The latter means it is easy for your code=
=20
> user to forget to catch exceptions at all.=20
>
> =E2=80=94 Calling abort(), directly or as result of ASSERT, is no bette=
r then=20
> silently ignoring the error. I'm pretty sure nobody wants their=20
> enterprise level system to shut down without even syncing disk cache=
=20
> and database transactions due to forgotten null pointer passed to=20
> logger function.=20
>
> =E2=80=94 Ditto for not checking arguments at all.=20
>
>
> =3D=3D=3D The proposed solution =3D=3D=3D=20
>
> The problem could be completely eliminated in many cases if pointers=20
> were not allowed to carry invalid values at all. These days C++ has a=20
> strong movement toward smart pointers, leaving plain C pointers as a=20
> legacy option or for very low-level things. Classes std::shared_ptr and=
=20
> std::weak_ptr are commonly seen as a replacement.=20
>
> Shared pointers are designed to mimic the behavior of plain pointers,=20
> they can wrap any pointer, even the one which is not safe to deallocate=
=20
> using "delete" operator. It offers its user a great number of ways to=20
> misuse it.=20
>
> I propose to create a subclass of shared pointers, which is somewhat=20
> guaranteed to hold a valid object which can be safely deallocated. This=
=20
> class should:=20
>
> =E2=80=94 be unable to hold nullptr;=20
> =E2=80=94 have no conversion constructors from plain pointers;=20
> =E2=80=94 have object allocation to be the only way for pointer to be o=
btained.=20
>
> Lets call this class an std::object_ptr, after the term "object" which=20
> is used throughout C++ standard text, and declare it like the following:=
=20
>
> template <typename T>=20
> class object_ptr: public std::shared_ptr<T> {=20
> + only copy and move constructors;=20
> + all operators applicable to std::shared_ptr<T>;=20
> }=20
>
> template <typename T, typename TAlloc, typename... TArgs>=20
> object_ptr<T> allocate_object(const TAlloc& a, TArgs&&... args);=20
>
> template <typename T, typename... TArgs>=20
> object_ptr<T> make_object(TArgs&&... args);=20
>
> The instance of the class must also be convertible to a shared pointer=20
> which is never empty or null.=20
>
> After the class is introduced, you may simply write your functions=20
> arguments as std::object_ptr<T> if you expect them to be pointers to=20
> valid objects only and just skip any further null-pointer validation, or=
=20
> leave them as std::shared_ptr<T> in cases there nullability makes sense.=
=20
> Or better use std::object_ptr together with std::optional, like the=20
> following:=20
>
> void Scene::paintSprite(const object_ptr<Sprite>&);=20
>
> std::optional<std::shared_ptr<Sprite>>=20
> Scene::findSprite(const Point&);=20
>
> In the example above it is clear from the very declaration that painting=
=20
> null sprite is not allowed (as being pointless) while function=20
> "findSpline" can return sprite if it is able to find one, or can return=
=20
> nothing otherwise.=20
>
> We should also provide a way to create std::object_ptr from=20
> std::shared_ptr or even plain pointers for legacy purposes, but there=20
> should be the only one point there such a conversion is allowed. I'm not=
=20
> quite sure about the exact name and signature, but it should be a single=
=20
> function like that:=20
>
> template <typename T>=20
> std::object_ptr<T> object_ptr_cast(const std::shared_ptr<T>&)=20
> throw(std::invalid_argument);=20
>
> =3D=3D=3D Conclusion =3D=3D=3D=20
>
> Eliminating null pointers validation may seem to be not that big deal to=
=20
> create a special pointer type for that, but indeed it is a great=20
> problem: thousands of people around the world, writing programs in=20
> various languages, every day performs a lot of useless checks against=20
> NULL, just to throw an exception which in most cases will never be=20
> caught. We must do something to left those legacy checks behind and thus=
=20
> improve code readability and "self-documentability".=20
>
> To improve the situation, Java has introduced @NonNull arguments=20
> attribute years ago (which is anyway broken), Scala uses the Optional[T]=
=20
> pattern (as many other functional languages). There are languages like=20
> Kotlin, which sees "T" as non-nulable reference by default and require=20
> user to explicitly declare nullable references like "T?". (Moreover,=20
> Kotlin can check arguments during compilation, with respect to code path=
=20
> branching.) I think this approach will be widely adopted in the future=20
> programming languages and C++ must take some steps in this direction.=20
>
>
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2398_1630773898.1448101489019
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I completely support this idea and its concept may even be=
come part of my scientific work. The only problem is to find appropriate, m=
eaningful, consistent names for non-nullable pointers.<div><br></div><div>N=
ulls (None's, nil's) are headache in C++, C#, Java, Python, Objecti=
ve C and so on.</div><div><br></div><div>Contract should be as explicit as =
possible. The earlier arguments are checked the less harmful potential cons=
equences are.<br><br>On Sunday, March 8, 2015 at 10:24:45 AM UTC+3, Pavel K=
retov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hello everybody.
<br>
<br>The problem I want you to discuss may have been already reviewed here,=
=20
<br>but I did not found anything similar in the mailing list archive. I was=
=20
<br>trying to explain the idea as well as I could, but I'm not a native=
=20
<br>speaker, so I might fail at some points. Excuse me for that.
<br>
<br>Have an nice weekend,
<br>=E2=80=94=E2=80=94=E2=80=94 Pavel Kretov.
<br>
<br>
<br>=3D=3D=3D The problem =3D=3D=3D
<br>
<br>This is a common practice in programming to check input parameters for
<br>functions. As many parameters are pointers, smart or regular, checking
<br>them against "nullptr" is a *very* frequent operation, but wh=
at should=20
<br>you do if pointer is null? There are many options:
<br>
<br>=C2=A0 =E2=80=94 silently return from the function?
<br>=C2=A0 =E2=80=94 print warning message and return?
<br>=C2=A0 =E2=80=94 throw an exception?
<br>=C2=A0 =E2=80=94 call abort() from <cstdlib>?
<br>=C2=A0 =E2=80=94 use some kind of ASSERT() and hope it will do the righ=
t thing?
<br>=C2=A0 =E2=80=94 skip the check altogether and get a segfault in case?
<br>
<br>The exact choice may be different for different projects but each has=
=20
<br>its own drawbacks.
<br>
<br>=C2=A0 =E2=80=94 If you chose to silently return, can you be sure that =
this is safe
<br>=C2=A0 =C2=A0 for the caller to stay unaware? Missing required paramete=
r is a
<br>=C2=A0 =C2=A0 programmer's mistake and they should be told of it as=
soon as
<br>=C2=A0 =C2=A0 possible.
<br>
<br>=C2=A0 =E2=80=94 If you chose to throw an exception, which one would yo=
u throw? Unlike
<br>=C2=A0 =C2=A0 languages like Java, C# or Python, C++ has a relatively p=
oor set of
<br>=C2=A0 =C2=A0 predefined exceptions. It is also considered to be a good=
practice
<br>=C2=A0 =C2=A0 in C++ to trow and exception only in case of really excep=
tional
<br>=C2=A0 =C2=A0 situations and a single null pointer does not seem to be =
that much
<br>=C2=A0 =C2=A0 serious matter. Moreover, when choosing exceptions you wi=
ll have to
<br>=C2=A0 =C2=A0 either pollute your functions' throw lists with std::=
invalid_argument
<br>=C2=A0 =C2=A0 or just omit them entirely. The latter means it is easy f=
or your code
<br>=C2=A0 =C2=A0 user to forget to catch exceptions at all.
<br>
<br>=C2=A0 =E2=80=94 Calling abort(), directly or as result of ASSERT, is n=
o better then
<br>=C2=A0 =C2=A0 silently ignoring the error. I'm pretty sure nobody w=
ants their
<br>=C2=A0 =C2=A0 enterprise level system to shut down without even syncing=
disk cache
<br>=C2=A0 =C2=A0 and database transactions due to forgotten null pointer p=
assed to
<br>=C2=A0 =C2=A0 logger function.
<br>
<br>=C2=A0 =E2=80=94 Ditto for not checking arguments at all.
<br>
<br>
<br>=3D=3D=3D The proposed solution =3D=3D=3D
<br>
<br>The problem could be completely eliminated in many cases if pointers=20
<br>were not allowed to carry invalid values at all. These days C++ has a=
=20
<br>strong movement toward smart pointers, leaving plain C pointers as a=20
<br>legacy option or for very low-level things. Classes std::shared_ptr and=
=20
<br>std::weak_ptr are commonly seen as a replacement.
<br>
<br>Shared pointers are designed to mimic the behavior of plain pointers,=
=20
<br>they can wrap any pointer, even the one which is not safe to deallocate=
=20
<br>using "delete" operator. It offers its user a great number of=
ways to=20
<br>misuse it.
<br>
<br>I propose to create a subclass of shared pointers, which is somewhat=20
<br>guaranteed to hold a valid object which can be safely deallocated. This=
=20
<br>class should:
<br>
<br>=C2=A0 =E2=80=94 be unable to hold nullptr;
<br>=C2=A0 =E2=80=94 have no conversion constructors from plain pointers;
<br>=C2=A0 =E2=80=94 have object allocation to be the only way for pointer =
to be obtained.
<br>
<br>Lets call this class an std::object_ptr, after the term "object&qu=
ot; which=20
<br>is used throughout C++ standard text, and declare it like the following=
:
<br>
<br>=C2=A0 =C2=A0 =C2=A0template <typename T>
<br>=C2=A0 =C2=A0 =C2=A0class object_ptr: public std::shared_ptr<T> {
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0+ only copy and move constructors;
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0+ all operators applicable to std::sh=
ared_ptr<T>;
<br>=C2=A0 =C2=A0 =C2=A0}
<br>
<br>=C2=A0 =C2=A0 =C2=A0template <typename T, typename TAlloc, typename.=
... TArgs>
<br>=C2=A0 =C2=A0 =C2=A0object_ptr<T> allocate_object(const TAlloc&am=
p; a, TArgs&&... args);
<br>
<br>=C2=A0 =C2=A0 =C2=A0template <typename T, typename... TArgs>
<br>=C2=A0 =C2=A0 =C2=A0object_ptr<T> make_object(TArgs&&... =
args);
<br>
<br>The instance of the class must also be convertible to a shared pointer=
=20
<br>which is never empty or null.
<br>
<br>After the class is introduced, you may simply write your functions=20
<br>arguments as std::object_ptr<T> if you expect them to be pointers=
to=20
<br>valid objects only and just skip any further null-pointer validation, o=
r=20
<br>leave them as std::shared_ptr<T> in cases there nullability makes=
sense.=20
<br>Or better use std::object_ptr together with std::optional, like the=20
<br>following:
<br>
<br>=C2=A0 =C2=A0 =C2=A0void Scene::paintSprite(const object_ptr<Sprite&=
gt;&);
<br>
<br>=C2=A0 =C2=A0 =C2=A0std::optional<std::shared_<wbr>ptr<Sprite>=
>
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Scene::findSprite(const Point&);
<br>
<br>In the example above it is clear from the very declaration that paintin=
g=20
<br>null sprite is not allowed (as being pointless) while function=20
<br>"findSpline" can return sprite if it is able to find one, or =
can return=20
<br>nothing otherwise.
<br>
<br>We should also provide a way to create std::object_ptr from=20
<br>std::shared_ptr or even plain pointers for legacy purposes, but there=
=20
<br>should be the only one point there such a conversion is allowed. I'=
m not=20
<br>quite sure about the exact name and signature, but it should be a singl=
e=20
<br>function like that:
<br>
<br>=C2=A0 =C2=A0 =C2=A0template <typename T>
<br>=C2=A0 =C2=A0 =C2=A0std::object_ptr<T> object_ptr_cast(const std:=
:shared_ptr<T>&)
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0throw(=
std::invalid_argument);
<br>
<br>=3D=3D=3D Conclusion =3D=3D=3D
<br>
<br>Eliminating null pointers validation may seem to be not that big deal t=
o=20
<br>create a special pointer type for that, but indeed it is a great=20
<br>problem: thousands of people around the world, writing programs in=20
<br>various languages, every day performs a lot of useless checks against=
=20
<br>NULL, just to throw an exception which in most cases will never be=20
<br>caught. We must do something to left those legacy checks behind and thu=
s=20
<br>improve code readability and "self-documentability".
<br>
<br>To improve the situation, Java has introduced @NonNull arguments=20
<br>attribute years ago (which is anyway broken), Scala uses the Optional[T=
]=20
<br>pattern (as many other functional languages). There are languages like=
=20
<br>Kotlin, which sees "T" as non-nulable reference by default an=
d require=20
<br>user to explicitly declare nullable references like "T?". (Mo=
reover,=20
<br>Kotlin can check arguments during compilation, with respect to code pat=
h=20
<br>branching.) I think this approach will be widely adopted in the future=
=20
<br>programming languages and C++ must take some steps in this direction.
<br>
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2398_1630773898.1448101489019--
------=_Part_2397_464074427.1448101489019--
.