cppfront
cppfront copied to clipboard
[DISCUSSION] type casting and correctness
Something I haven't seen addressed or talked about is how cppfront or the new cpp2 syntax will handle type casting. When I write code, I try to be very explicit and specific with my types and that includes adding a ton of casts. I also do thing such as turn on -pendaic and -Werror to catch any type casts that I might have missed to do.
Is there any proposal to make casting easier and simpler?
E.g., I've never understood why I might get a warning/error from a compiler if I do this:
int32_t a = 0;
int64_t b = a;
I can understand the cast from 64 -> 32 bits, since there is a loss in precision. But not from going 32 -> 64 bits since there is a growth in the precision.
Talking about the syntax for the moment, I've also had my share of colleagues who don't like writing out static_cast<> because they thing "It's too long to type out when just a simple C-style cast suffices.". Is there a syntactical change that could be make to make proper casting easier?. E.g. reduce static_cast<> to scast<>?
I'm also not sure if the names of static_cast, dynamic_cast, reinterpret_cast and const_cast are that great, as when I first was learning C++ a decade+ ago I had trouble trying to understand the meaning of the assigned names.
There is a work regarding better casting and better inspection by using is and as keywords - check https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2392r0.pdf
I am currently implementing improved inspection mechanism (pull request is waiting here https://github.com/hsutter/cppfront/pull/79). Next I will jump into as casting to check if I can improve something or implement some missing features described in the p2392 paper.
Depending on the needs I can imagine that we can have syntax like:
fun(b as int32_t);
or something else that will be descriptive enough not to confuse the reader of the code.
I think I've see the as syntax before in other languages. The only thing that I have a little bit of an issue with is that the type is on the right side of the as. In C++, I'm used to seeing the types on the left side. Eg.:
int a = 2;
static_cast<float>(4);
new string("hi mom!");
The type is coming before the variable/argument. Would maybe a syntax like this be good:
fun(int32_t from b);
This still keeps the type on the left side of the equation.
This is the major change in the syntax: cpp2 is using left-to-right syntax. @hsutter explains more here: https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators
So the type will not be on the left side.
In cpp2 your examples will look like:
a : int = 2; // "a" is an int that equals 2
4 as float; // interpret 4 as float
new<string>("hi mom!"); // create unique pointer to string that equals "hi mom!"
and taking that into account the syntax
fun(b as int32_t);
is more natural.
The syntax is new and you have to use to it but later on it becomes natural. It is always {name_of_the_variable} {type} {value}.
Taking a look on the potential declaration of fun function:
// fun is a function that takes value argument
// of type int32_t and returns bool
fun: (value : int32_t) -> bool = {
// do something with value...
return true;
}
Please notice that the function arguments are also declared in the same pattern.
value : int32_t is similar to b as int32_t
I think this has been answered (thanks @filipsajdak !).
Something I haven't seen addressed or talked about is how cppfront or the new cpp2 syntax will handle type casting
As @filipsajdak said, in Cpp2 all type casting uses as. See this 1-min clip from the talk.
The only thing that I have a little bit of an issue with is that the type is on the right side of the
as
In general Cpp2 is left-to-right, not only for declarations but also for uses such as x.f(y) for unified function call syntax, for postfix operators, and for is and as expressions like x is T and x as T.
The principle is that by "starting with the name that already exists" we have a known starting point that we're going to do something to. This gives several advantages... for example:
- For function calls of the form
x.f(y)it enables high-quality autocomplete that is generally harder or impossible forf(x,y). (This does not require anyone to be a fan of call chaining styles ;) ) - For unary operators (which are nearly all postfix in Cpp2) it removes the prefix/postfix visual ambiguities and a lot of the
()parentheses required to do the right thing... postfix operators can be cleanly read as "next do this." For example, in today's C++ we might write++((*x)[0])(quick quiz: which of those parens are actually needed? can you answer without looking it up? are you sure enough that you wouldn't write them anyway just in case?). In Cpp2 that is written asx*[0]++which reads IMO-cleanly as "start withx, then dereference that, then subscript that, then increment that." (for more see Design note: Postfix operators).
The same left-to-right readability applies to is and as too.