-
Notifications
You must be signed in to change notification settings - Fork 249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SUGGESTION] Add support for defining type aliases. #273
Comments
I am currently missing that feature on the cpp2 side. I like the syntax. |
Nice feature, but one thing I'd like to point out, it's important to have distinction between actual user defined types and type aliases. The syntax could be same but we can have a different keyword instead of
Any keyword that fits can be chosen but it's the distinction which I emphasize that should be present. |
@AbhinavK00 You make a very good point and I've actually thought about this while implementing. Currently in my implementation, if initializer.statement is a If the distinction between UDTs and type aliases is significant enough to warrant an introduction of a new keyword, I could try implementing it that way as well. |
I've read in a comment from @hsutter that he wants to use
Edit: Also |
Good suggestion. I do intend to implement aliases down the road, and I haven't settled on a syntax for them yet. One issue with I am considering using |
What's your motivation for this, @AbhinavK00? |
No real motivation I guess but there should be a distinction between strong typedefs and just aliases to typenames.
This is just another name and DWORD can be used anywhere in place of u32, this doesn't have many use cases.
This is like wrapping an So no real motivation, but I just put it out in case if others agree. |
But what is a "strong typedef"? It'd be great if, down the road of development of Cpp2, we could find the answer meant for Cpp2. Although, with metaclasses, we might be able to author better answers than today's Cpp1. |
As a library author, when you export a type name sometimes it refers to a class you defined, and sometimes you want it to be just an alias to something else, without leaking that detail to the user of the library. In current C++ the leakage is unavoidable, for example because the user can forward-declare your classes, but not an alias. Hopefully in Cpp2 this specific case is not an issue because forward-declaring is made unnecessary. But the general request remains, of letting a library author export an alias that is indistinguishable from a type's "true" name.
I'm guessing Herb is thinking of compile-time modification of types, for which whether you're modifying the original or a copy makes a difference? |
On thinking about this further, two things:
So after some thought of brainstorming options, include ones that include
Checking it in now... |
Question: What does the following line mean?
And the point about Also, these are same as Edit: Nevermind, got it |
Thanks. Nice reasonable syntax. I think Maybe also |
I didn't 🙂 Is it supposed to mean that you can't "assign" something to the alias to bind it to something else? (But you already can't assign anything to a type name). |
I think it is like, you can't change the meaning of an alias. Something like the following: vec :== my_vector; //created alias
//lots of code here
vec == std::vector; //illegal I think it is that, but someone definitely chime in if i'm wrong or there's a better explanation. |
It is that:
|
Wait, I thought cpp2 was to remove references altogether? Isn't that just references in other form. |
I think that's an implementation detail. The point is having a general "alias" syntax. |
It's still redundant, one could do the same thing with non-mutating pointers (with a bit more writing). It's like, making different things look same. |
Then variable aliases would be different than the others, as it would require punctuation to refer to the aliased entity. 63efa6e's commit message is very informative. |
My point is, object aliases are not needed. You can already do that with pointers, which existed before the commit and aliasing objects is different from aliasing classes and namespaces, the former may/may not have a level of indirection with it whjle the latter does not (I have no idea how |
A fundamental difference between aliases to namespaces/types/functions, and C++ references to objects, is that the former things are "static" as in their lifetime is the lifetime of the program, and they're immutable. Their aliases are resolved by the compiler. C++ references to objects, instead, are pointers and are resolved and runtime (so come with a set of issues with lifetime and concurrency). From the way I'm seeing this implemented syntax, you cannot declare the type of a variable to be "alias to an object" (which would be equivalent to a C++ reference). So these aliases are just a "second name" that's resolved only at compile-time, and can't "escape" the current scope like a pointer can. |
In other words, this seems to me to be "give a second new name to this thing during compilation", and not "take the memory address of this and pass it around at runtime". |
The whole point of aliases is to give a better name to things that you don't have the control to rename like namespaces and classes/functions in them. Objects are made by the user, he can name them whatever he wants, why would he refer to it with a different name. This feature is so unnecessary. |
Yeah I wasn't commenting on the usefulness. Although "object aliases" is how function aliases are currently implemented, per the commit Johel pointed to. So I figure the use cases for aliasing a non-function object would be the same as why you'd want to alias a function:
Anyway I feel that "make aliases work for non-function objects too" wasn't done to satisfy existing use cases people were clamoring for. Rather to not add an exception to the language. Given the intended unification of "namespaces are like classes", "functions are just objects of function type", and all those things being declared with the same syntax. |
|
That supports my point! |
I suppose you'd want to undo |
It's supposed to be an lvalue. |
This is now #438. Moved contents.
A wild thought. Maybe a namespace declaration should use
How does that fit with the current Cpp2? |
By supporting nested namespace definition, the distinction from other declarations raises.
|
Varibles can be re-assigned so I don't think |
@JohelEGP, I like your idea. @AbhinavK00, Because On the other hand, point: type = {
x: int = 0;
y: int = 0;
operator=: (out this, arg_x: int, arg_y: int) = {
x = arg_x;
y = arg_y;
}
}
point: type += {
// Extension method
print: (this) = {
std::cout << x << ", " << y << '\n';
}
} Namesapces inherently won't be redefined, so only new declarations are added to them. It's going to be like this example in a similar manner to the previous example: // Maybe they should be defined at first with `=`
x: namespace = {}
x: namespace += {
func: () = {}
}
x: namespace += {
another_func: () = {}
}
main: () = {
x::func();
x::another_func();
} Ignore the followingUnhide contents...If Cpp2 could support extension methods, namespaces could be another metaclass function: // Maybe they should be defined at first with `=`
x: @namespace type = {}
x: @namespace type += {
func: () = {}
} It would merge namespace classes (types which only have static members) and namespaces to a single concept. EDIT: Types and namespaces have logically different behaviours in many ways in Cpp2. So you can ignore this part. |
if |
Variables can be assigned to, yes. Shadowing does redefine what the identifier means for the current scope.
I disagree. |
@JohelEGP I like your idea. I think it would be better if this discussion about namespaces (and namespace metaclass) were moved to a new, open issue for better visibility. |
The entry bar is a bit higher for suggestions, compared to continue piling up on an issue's discussion. But I did it: #438. |
I mean that Currently Cpp2 doesn't support local functions, but this is an example: a: = 0;
x: () = {};
{
a: = 1;
// It seems X is redefined, but underhood it's another function.
x: () = {};
} (This example is just my thought about how local functions may be available in the future.) |
More precisely, point: type = {
operator=: (out this, x: int, y: int) = {}
}
main: () = {
// It declares `x` is a `point`.
x: point;
// It defines `x` with constructor.
// It generates: `x.construct(0, 0);`
x = (0, 0);
} You're right. Requiring to define namespaces with |
I wonder if that's how you'd describe it in Cpp2. |
A declaration without |
The thing is, |
The first assignment is the definition: point: type = {
operator=: (out this, x: int, y: int) = {}
}
main: () = {
// Declaration and definition
v: point = (0, 0);
// Declaration
u: point;
// Definition
// It generates: `u.construct(0, 0);`
u = (0, 0);
// ERROR! This is not a definition.
// BTW it generates wrong Cpp1: `u.value() = 1, 1;`
u = (1, 1);
} |
It seems plausible that the definite first assignment is the definition. Thinking about definite first assignment made me remember that Cpp2 doesn't have forward declarations. In Cpp2, things that can be without an initializer are:
|
An alias can be to a namespace, type, function, or object. Aliases are always a non-mutable view of the original entity. This is natural for namespace and type and function aliases, since those kinds of entited can't be mutated, but it bears calling out for an object alias which behaves as `auto const&`. The current syntax is like non-alias declarations, but with `==` to connote equality with an existing entity, instead of `=` which connotes setting the new entity's value. For example: lit: namespace == ::std::literals; pmr_vec: <T> type == std::vector<T, std::pmr::polymorphic_allocator<T>>; func :== some_original::inconvenient::function_name; vec :== my_vector; // note: const&, aliases are never mutable Note: Function aliases are subsumed under the object case, so you can't declare a function alias with an explicit signature. Rationale: - if there's no need for a (repetitive) explicit signature, the object case covers it - if the parameters/returns must be exact (no conversions), a pointer to function covers it - if parameter/return conversions are allowed, std::function covers it But if we do learn about a reason to add support for function aliases having an explicit signature, and possibly with conversions to/from the parameter/return types, they'll be a natural fit here.
Recently cppfront added the ability to define user-defined types. I want to extend this feature to be able to declare type aliases. My proposed syntax looks like this:
This will be compiled to (skipping boilerplate):
Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?
No.
Will your feature suggestion automate or eliminate X% of current C++ guidance literature?
Yes, this syntax uses the l-to-r declaration syntax already used widely in Cpp2, so there's no need to teach the syntax
using alias_name = type_name
.I have already implemented this feature locally so I can provide a PR.
The text was updated successfully, but these errors were encountered: