# Whither C++? food for thought

**URL:** <https://discourse.ats-lang.org/t/whither-c-food-for-thought/145>\
**Category:** Google Group\
**Created:** [March 4, 2016, 8:24pm UTC](https://discourse.ats-lang.org/t/whither-c-food-for-thought/145 "2016-03-04T20:24:07Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Raoul\_Duke](https://avatars.discourse-cdn.com/v4/letter/r/bbe5ce/32.png) [@Raoul\_Duke](https://discourse.ats-lang.org/u/Raoul_Duke)\
**Post date:** [March 4, 2016, 8:24pm UTC](https://discourse.ats-lang.org/t/whither-c-food-for-thought/145/1 "2016-03-04T20:24:07Z")

</div>

From Stroustrup, Sutter, and Dos Reis  
([https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf](https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf))

How do you feel ATS compares with “good” C++, in particular:

(1) "Adding finalizers to GC partially addresses this problem but even  
something as simple and well-known as calling fclose() at GC time is  
almost always unsuitable. Finalizers:

- are executed at a nondeterministic time on a system thread, which  
can inject deadlocks with program threads;
- are not guaranteed to run at all, so there is no guarantee the file  
will ever be closed as long as the program is running;
- can lead to excessive resource retention when the GC is not run  
frequently; and
- can make GC unnecessarily expensive if a finalizer can place a  
reference to an object it was supposed to destroy in an accessible  
location (“resurrection”).  
Consequently, the use of finalizers for resource cleanup is now  
actively discouraged in the major GC environments that support them,  
leaving the release of non-memory resources as a manual activity."

(2) “Using owner and static analysis is unmanageable for “ordinary  
C-style code”. We would simply need too many owner annotation so that  
those annotations would themselves become a nuisance and a source of  
errors. This has been seen in languages depending on annotations (such  
as Cyclone and Microsoft’s SAL annotations for C and C++ code) and our  
own experiments. To be manageable on an industrial scale, owner  
annotation must be rare. We ensure that by “burying” them in proper  
ownership abstractions, such as vectors and unique\_ptrs.”

(3) “As for dangling pointers and for ownership, this model detects  
all possible errors. This means that we can guarantee that a program  
is free of uses of invalidated pointers. There are many control  
structures in C++, addresses of objects can appear in many guises  
(e.g., pointers, references, smart pointers, iterators), and objects  
can “live” in many places (e.g., local variables, global variables,  
standard containers, and arrays on the free store). Our tool  
systematically considers all combinations. Needless to say, that  
implies a lot of careful implementation work (described in detail in  
[Sutter,2015]), but it is in principle simple: all uses of invalid  
pointers are caught.”

(4) “Note that this is still local analysis; we just look at a  
function declaration with respect to possible invalidation. When  
invalidation is possible, we must be conservative and assume the  
worst. We consider whole-program analysis incompatible with the needs  
of large programs, the need for a fast debug cycle, and the needs of a  
language supporting dynamic linking. Whole-program can be useful, and  
we will use it, but not in the usual debug cycle.”

(5) “This technique of moving objects rather than copying them has  
been used for decades, but only infrequently and unsystematically. The  
notion of direct language support for move semantics was pioneered by  
Howard Hinnant and is part of C++11. The use of move semantics allows  
us to move a large object implemented as a handle from scope to scope  
without overhead and without resorting to error-prone explicit use of  
pointers and explicit memory management.  
One implication of having move semantics is that we can completely  
encapsulate the management of non-scoped memory.”

(6) “For most resources (memory, locks, file handles, etc.),  
acquisition can fail so a conventional resource manager must be able  
to report an error. The only fully general mechanism for that is  
throwing an exception if resource acquisition fails, and that’s what  
the standard containers do. This scheme handles nested objects, class  
hierarchies, and containers simply and efficiently. However, there are  
also schemes that rely on explicit error handling. Those are brittle  
and rarely generalize; the best basically hand- simulate RAII.”

(7) “The model presented so far relies on sequential execution in a  
language with lexical scoping. In a multi- threaded system, we need to  
handle more cases.  
Our rule set for concurrency is not yet fully developed. In  
particular, detached threads with pointers to shared data can be  
tricky. However, threads that are joined at the end of their scopes  
can be analyzed much as called functions and shared\_ptrs can be used  
to keep data alive for threads with less well- behaved lifetimes.  
There are also obvious opportunities for tools that analyze for race  
conditions and deadlocks.”

(8) “Here, we will only briefly mention other ways of breaking the C++  
type system. These problems are well known and have well-known  
solutions, so we will not address them here. Misuse of unions and  
casts can lead to type and memory violations (so follow the rules that  
prevent that [Stroustrup,2015]). For example, use a variant class  
rather than a plain union. Out-of-range access and access through a  
null pointer can lead to type and memory errors (so follow the rules  
that prevent that). In particular, use array\_view and not\_null from  
the Guideline Support Library (GSL) [Sutter, 2015b]. To minimize range  
errors, we also recommend using a make\_array() function that returns  
an owner\<array\_view\> to allocate an array on the free store, rather  
than using new or malloc() directly. The aim of the Code Guidelines is  
to eliminate a large range of errors by mutually supportive rules. No  
one rule can by itself prevent a large class of errors: ban one misuse  
and others will become popular (this is often referred to as “playing  
whack-a-mole”). Thus, our ideal is a large set of mutually supportive  
rules that together deliver type and memory safety guarantees.”

---

<div class="post-metadata">

**Author:** ![Raoul\_Duke](https://avatars.discourse-cdn.com/v4/letter/r/bbe5ce/32.png) [@Raoul\_Duke](https://discourse.ats-lang.org/u/Raoul_Duke)\
**Post date:** [March 5, 2016, 5:07pm UTC](https://discourse.ats-lang.org/t/whither-c-food-for-thought/145/2 "2016-03-05T17:07:29Z")

</div>

Nice analysis. 🙂

---

<div class="post-metadata">

**Author:** ![gmhwxi](https://avatars.discourse-cdn.com/v4/letter/g/67e7ee/32.png) [@gmhwxi](https://discourse.ats-lang.org/u/gmhwxi)\
**Post date:** [March 5, 2016, 3:18pm UTC](https://discourse.ats-lang.org/t/whither-c-food-for-thought/145/3 "2016-03-05T15:18:18Z")

</div>

When I say C++ is complex, it is a bit like saying that politics is complex.

When I say ATS is complex, I mostly mean that mathematics is complex.On Friday, March 4, 2016 at 5:43:29 PM UTC-5, gmhwxi wrote:

> I feel that coding in C++ is too complex and coding in “good” C++  
> is even more complex. No matter how wonderful a feature is, a programmer  
> has to learn it. IMHO, any programmer has only a limited learning capacity.
> 
> Yes, ATS is complex, too. But there is at least a collection of typing  
> rules in ATS that type-theorists can grasp without too much difficulty.  
> More importantly, the consistency of these typing rules is formally  
> established.  
> You probably could not say the same about C++.
> 
> On Friday, March 4, 2016 at 3:24:08 PM UTC-5, Raoul Duke wrote:
> 
> > From Stroustrup, Sutter, and Dos Reis  
> > (  
> > [https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf](https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf))
> > 
> > How do you feel ATS compares with “good” C++, in particular:
> > 
> > (1) "Adding finalizers to GC partially addresses this problem but even  
> > something as simple and well-known as calling fclose() at GC time is  
> > almost always unsuitable. Finalizers:
> > 
> > - are executed at a nondeterministic time on a system thread, which  
> > can inject deadlocks with program threads;
> > - are not guaranteed to run at all, so there is no guarantee the file  
> > will ever be closed as long as the program is running;
> > - can lead to excessive resource retention when the GC is not run  
> > frequently; and
> > - can make GC unnecessarily expensive if a finalizer can place a  
> > reference to an object it was supposed to destroy in an accessible  
> > location (“resurrection”).  
> > Consequently, the use of finalizers for resource cleanup is now  
> > actively discouraged in the major GC environments that support them,  
> > leaving the release of non-memory resources as a manual activity."
> > 
> > (2) “Using owner and static analysis is unmanageable for “ordinary  
> > C-style code”. We would simply need too many owner annotation so that  
> > those annotations would themselves become a nuisance and a source of  
> > errors. This has been seen in languages depending on annotations (such  
> > as Cyclone and Microsoft’s SAL annotations for C and C++ code) and our  
> > own experiments. To be manageable on an industrial scale, owner  
> > annotation must be rare. We ensure that by “burying” them in proper  
> > ownership abstractions, such as vectors and unique\_ptrs.”
> > 
> > (3) “As for dangling pointers and for ownership, this model detects  
> > all possible errors. This means that we can guarantee that a program  
> > is free of uses of invalidated pointers. There are many control  
> > structures in C++, addresses of objects can appear in many guises  
> > (e.g., pointers, references, smart pointers, iterators), and objects  
> > can “live” in many places (e.g., local variables, global variables,  
> > standard containers, and arrays on the free store). Our tool  
> > systematically considers all combinations. Needless to say, that  
> > implies a lot of careful implementation work (described in detail in  
> > [Sutter,2015]), but it is in principle simple: all uses of invalid  
> > pointers are caught.”
> > 
> > (4) “Note that this is still local analysis; we just look at a  
> > function declaration with respect to possible invalidation. When  
> > invalidation is possible, we must be conservative and assume the  
> > worst. We consider whole-program analysis incompatible with the needs  
> > of large programs, the need for a fast debug cycle, and the needs of a  
> > language supporting dynamic linking. Whole-program can be useful, and  
> > we will use it, but not in the usual debug cycle.”
> > 
> > (5) “This technique of moving objects rather than copying them has  
> > been used for decades, but only infrequently and unsystematically. The  
> > notion of direct language support for move semantics was pioneered by  
> > Howard Hinnant and is part of C++11. The use of move semantics allows  
> > us to move a large object implemented as a handle from scope to scope  
> > without overhead and without resorting to error-prone explicit use of  
> > pointers and explicit memory management.  
> > One implication of having move semantics is that we can completely  
> > encapsulate the management of non-scoped memory.”
> > 
> > (6) “For most resources (memory, locks, file handles, etc.),  
> > acquisition can fail so a conventional resource manager must be able  
> > to report an error. The only fully general mechanism for that is  
> > throwing an exception if resource acquisition fails, and that’s what  
> > the standard containers do. This scheme handles nested objects, class  
> > hierarchies, and containers simply and efficiently. However, there are  
> > also schemes that rely on explicit error handling. Those are brittle  
> > and rarely generalize; the best basically hand- simulate RAII.”
> > 
> > (7) “The model presented so far relies on sequential execution in a  
> > language with lexical scoping. In a multi- threaded system, we need to  
> > handle more cases.  
> > Our rule set for concurrency is not yet fully developed. In  
> > particular, detached threads with pointers to shared data can be  
> > tricky. However, threads that are joined at the end of their scopes  
> > can be analyzed much as called functions and shared\_ptrs can be used  
> > to keep data alive for threads with less well- behaved lifetimes.  
> > There are also obvious opportunities for tools that analyze for race  
> > conditions and deadlocks.”
> > 
> > (8) “Here, we will only briefly mention other ways of breaking the C++  
> > type system. These problems are well known and have well-known  
> > solutions, so we will not address them here. Misuse of unions and  
> > casts can lead to type and memory violations (so follow the rules that  
> > prevent that [Stroustrup,2015]). For example, use a variant class  
> > rather than a plain union. Out-of-range access and access through a  
> > null pointer can lead to type and memory errors (so follow the rules  
> > that prevent that). In particular, use array\_view and not\_null from  
> > the Guideline Support Library (GSL) [Sutter, 2015b]. To minimize range  
> > errors, we also recommend using a make\_array() function that returns  
> > an owner\<array\_view\> to allocate an array on the free store, rather  
> > than using new or malloc() directly. The aim of the Code Guidelines is  
> > to eliminate a large range of errors by mutually supportive rules. No  
> > one rule can by itself prevent a large class of errors: ban one misuse  
> > and others will become popular (this is often referred to as “playing  
> > whack-a-mole”). Thus, our ideal is a large set of mutually supportive  
> > rules that together deliver type and memory safety guarantees.”

---

<div class="post-metadata">

**Author:** ![gmhwxi](https://avatars.discourse-cdn.com/v4/letter/g/67e7ee/32.png) [@gmhwxi](https://discourse.ats-lang.org/u/gmhwxi)\
**Post date:** [March 4, 2016, 10:43pm UTC](https://discourse.ats-lang.org/t/whither-c-food-for-thought/145/4 "2016-03-04T22:43:29Z")

</div>

I feel that coding in C++ is too complex and coding in “good” C++  
is even more complex. No matter how wonderful a feature is, a programmer  
has to learn it. IMHO, any programmer has only a limited learning capacity.

Yes, ATS is complex, too. But there is at least a collection of typing  
rules in ATS that type-theorists can grasp without too much difficulty.  
More importantly, the consistency of these typing rules is formally  
established.  
You probably could not say the same about C++.On Friday, March 4, 2016 at 3:24:08 PM UTC-5, Raoul Duke wrote:

> From Stroustrup, Sutter, and Dos Reis  
> (  
> [https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf](https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Introduction%20to%20type%20and%20resource%20safety.pdf))
> 
> How do you feel ATS compares with “good” C++, in particular:
> 
> (1) "Adding finalizers to GC partially addresses this problem but even  
> something as simple and well-known as calling fclose() at GC time is  
> almost always unsuitable. Finalizers:
> 
> - are executed at a nondeterministic time on a system thread, which  
> can inject deadlocks with program threads;
> - are not guaranteed to run at all, so there is no guarantee the file  
> will ever be closed as long as the program is running;
> - can lead to excessive resource retention when the GC is not run  
> frequently; and
> - can make GC unnecessarily expensive if a finalizer can place a  
> reference to an object it was supposed to destroy in an accessible  
> location (“resurrection”).  
> Consequently, the use of finalizers for resource cleanup is now  
> actively discouraged in the major GC environments that support them,  
> leaving the release of non-memory resources as a manual activity."
> 
> (2) “Using owner and static analysis is unmanageable for “ordinary  
> C-style code”. We would simply need too many owner annotation so that  
> those annotations would themselves become a nuisance and a source of  
> errors. This has been seen in languages depending on annotations (such  
> as Cyclone and Microsoft’s SAL annotations for C and C++ code) and our  
> own experiments. To be manageable on an industrial scale, owner  
> annotation must be rare. We ensure that by “burying” them in proper  
> ownership abstractions, such as vectors and unique\_ptrs.”
> 
> (3) “As for dangling pointers and for ownership, this model detects  
> all possible errors. This means that we can guarantee that a program  
> is free of uses of invalidated pointers. There are many control  
> structures in C++, addresses of objects can appear in many guises  
> (e.g., pointers, references, smart pointers, iterators), and objects  
> can “live” in many places (e.g., local variables, global variables,  
> standard containers, and arrays on the free store). Our tool  
> systematically considers all combinations. Needless to say, that  
> implies a lot of careful implementation work (described in detail in  
> [Sutter,2015]), but it is in principle simple: all uses of invalid  
> pointers are caught.”
> 
> (4) “Note that this is still local analysis; we just look at a  
> function declaration with respect to possible invalidation. When  
> invalidation is possible, we must be conservative and assume the  
> worst. We consider whole-program analysis incompatible with the needs  
> of large programs, the need for a fast debug cycle, and the needs of a  
> language supporting dynamic linking. Whole-program can be useful, and  
> we will use it, but not in the usual debug cycle.”
> 
> (5) “This technique of moving objects rather than copying them has  
> been used for decades, but only infrequently and unsystematically. The  
> notion of direct language support for move semantics was pioneered by  
> Howard Hinnant and is part of C++11. The use of move semantics allows  
> us to move a large object implemented as a handle from scope to scope  
> without overhead and without resorting to error-prone explicit use of  
> pointers and explicit memory management.  
> One implication of having move semantics is that we can completely  
> encapsulate the management of non-scoped memory.”
> 
> (6) “For most resources (memory, locks, file handles, etc.),  
> acquisition can fail so a conventional resource manager must be able  
> to report an error. The only fully general mechanism for that is  
> throwing an exception if resource acquisition fails, and that’s what  
> the standard containers do. This scheme handles nested objects, class  
> hierarchies, and containers simply and efficiently. However, there are  
> also schemes that rely on explicit error handling. Those are brittle  
> and rarely generalize; the best basically hand- simulate RAII.”
> 
> (7) “The model presented so far relies on sequential execution in a  
> language with lexical scoping. In a multi- threaded system, we need to  
> handle more cases.  
> Our rule set for concurrency is not yet fully developed. In  
> particular, detached threads with pointers to shared data can be  
> tricky. However, threads that are joined at the end of their scopes  
> can be analyzed much as called functions and shared\_ptrs can be used  
> to keep data alive for threads with less well- behaved lifetimes.  
> There are also obvious opportunities for tools that analyze for race  
> conditions and deadlocks.”
> 
> (8) “Here, we will only briefly mention other ways of breaking the C++  
> type system. These problems are well known and have well-known  
> solutions, so we will not address them here. Misuse of unions and  
> casts can lead to type and memory violations (so follow the rules that  
> prevent that [Stroustrup,2015]). For example, use a variant class  
> rather than a plain union. Out-of-range access and access through a  
> null pointer can lead to type and memory errors (so follow the rules  
> that prevent that). In particular, use array\_view and not\_null from  
> the Guideline Support Library (GSL) [Sutter, 2015b]. To minimize range  
> errors, we also recommend using a make\_array() function that returns  
> an owner\<array\_view\> to allocate an array on the free store, rather  
> than using new or malloc() directly. The aim of the Code Guidelines is  
> to eliminate a large range of errors by mutually supportive rules. No  
> one rule can by itself prevent a large class of errors: ban one misuse  
> and others will become popular (this is often referred to as “playing  
> whack-a-mole”). Thus, our ideal is a large set of mutually supportive  
> rules that together deliver type and memory safety guarantees.”
