Skip to content
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

Accepts some statements of C++; typedef, friend, override and final #9465

Closed
samchon opened this issue Jul 1, 2016 · 4 comments
Closed

Accepts some statements of C++; typedef, friend, override and final #9465

samchon opened this issue Jul 1, 2016 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@samchon
Copy link

samchon commented Jul 1, 2016

Accepts some statements of C++

I have made a STL (Standard Template Library, a standard libraries with containers, functions and algorithms of C++) for TypeScript, named TypeScript-STL. Well, because I've tried to migrate C++ code to TypeScript, I strongly aspire TypeScript to accept some grammers and conceptions of C++, typedef, friend, override and final.

TypeDef

Well, I don't mean to accept typedef statement of C++, literally. TpyeScript already has similar conception with type statement. The type statement can be used in root of document, in a namespace and even in a function body. However, the type statement only can't be used in a class level.

I want the type statement can be used in a class level such below:

type can be declared in a namespace or function.
namespace std
{
    // I CAN IMMITATE typedef WITH THOSE CODES
    export type vector<T> = Vector<T>;
    export var vector = Vector;
}
I want the type can be declared in a class elvel.
namespace std
{
    // HOWEVER, DEFINING TYPE IN A CLASS IS IMPOSSIBLE
    class Vector<T>
    {
        // IT'S IMPOSSIBLE.
        // Unexpected token. A constructor, method, accessor, or property was expected.
        public static type iterator = VectorIterator<T>; 
    }
}

Friend

TypeScript is a superset language of JavaScript. Member variables and methods with private and protected accessors are only effective in TypeScript. When compiled to JavaScript, those accessors are all detached. Thus, TypeScript also can access the private and protected members by dynamic accessment like such below:

class Member
{
    private id: string;
    private email: string;
}

var member: Member = new Member();;
member["id"] = "samchon";
(member as any).email = "samchon@samchon.org";

Those dynamic accessing are not recommended, but one thing clear is, it is possible in TypeScript. As anyone knows, those implementation using string brackets (obj["member_name"]) are not safe. Those implementation can't take advantage of type inspection, the best benefit of TypeScript.

If TypeScript supports the friend statement, then the dangerous method without type-inspection can be solved. Accessing private and protected members with friend statement in C++ sometimes beging criticized, however, it's sometimes useful especially for implementing libraries. Furthermore, it can solve the dangerous dynamic accessing problem.

Below is the real code what I need the friend statement:

class List<T>
{
    // DEFINING TYPE IN CLASS IS POSSIBLE
    public static type iterator = ListIterator<T>;
    public static type reverse_iterator = ListReverseIterator<T>;

    // ONLY List CAN CREATE ListIterator
    private begin_: ListIterator<T>;
    private end_: ListIterator<T>;

    public begin(): ListIterator<T>;
    public end(): ListIterator<T>;

    // ONLY List CAN CREATE ListIterator
    public rbegin(): ListReverseIterator<T>;
    public rend(): ListReverseIterator<T>;
}

class ListIterator<T>
{
    // ListIterator IS ONLY ACCESSED BY List
    friend class List<T>;

    // THOSE NODE MEMBERS, ALSO MODIFIED BY List
    private prev: ListIterator<T>;
    private next: ListIterator<T>;
    private value: T;

    private constructor(source: List<T>, prev: ListIterator<T>, next: ListIterator<T>, value: T);
}
class ListReverseIterator<T>
{
    // ListReverseIterator.constructor IS ONLY CALLED BY List
    friend class List<T>;
    private constructor(base: ListIterator<T>);
}

Override

To enhance grammer and stability, I want TypeScript to concept override statement.

Unlike Java, TypeScript doesn't have the conception overriding. TypeScript only can do over-writing. By the over-writing of parent's function, parameters or return type of the function can be changed. It's not a matter if the changing is intended, however, it's by a mistake, then there's no way to identify the mistake until runtime.

To avoid the mistake, I want TypeScript to adapt override statement. If programmer intends to overriding, then adds override statement on the tail of the overriden function. TypeScript compiler inspects and detects mistake the overriden functions by override statement.

Sample code is such below:

class Parent
{
    public sendData(invoke: Invoke): void;
    public replyData(invoke: Invoke): void;
}

class Child
{
    // OK, GOOD OVERRIDING
    public sendData(invoke: Invoke): void override;

    // OK, IT'S NOT OVERRIDING, BUT OVER-WRITING
    public sendData(invoke: Invoke, size: number): void;

    // ERROR. IT'S NOT OVER-RIDING, BUT OVER-WRITING
    public replyData(invoke: XML): void override;
}

Final

Making open source libraries, I sometimes want to make a method unable to override (like non-virtual method in C++). Furthermore, an overriden method, already overriden method needs to prohibit re-overriding from its derived classes (virtual and overriden method, but does not permit re-overriden nomore).

To prohibit overriden by derived classes, I want TypeScript to accept the final statement. Sample codes are below:

An example code with final statement.
class GrandParent
{
    protected addClient(socket: Socket): void;
}

class Parent extends GrandParent
{
    // GOOD OVERRIDING
    // WITH FINAL STATEMENT, IT CAN'T BE OVERRIDEN MORE
    protected addClient(socket: Socket): void override final;
}

class Child extends Parent
{
    // IT'S ERROR. addClient CAN'T BE OVERRIDEN BY final STATEMENT in Parent.
    protected addClient(socket: Socket): void override; // ERROR
}
Real case needs the final statement.

Those are real codes what I need the final statement.

namespace std
{
    namespace base
    {
        abstract class MapContainer<Key, T>
        {
            protected abstract handle_insert(first: MapIterator<Key, T>, last: MapIterator<Key, T>): void;
            protected abstract handle_erase(first: MapIterator<Key, T>, last: MapIterator<Key, T>): void;   
        }
    }

    class HashMap<Key, T> extends base.MapContainer<Key, T>
    {
        private hash_buckets_: base.MapHashBuckets<Key, T>;

        // IT CAN'T BE OVERRIDEN MORE
        protected handle_insert(first: MapIterator<Key, T>, last: MapIterator<Key, T>): void override final
        {
            for (let it = first; !it.equal_to(last); it = it.next())
                this.hash_buckets_.insert(it);
        }

        // IT CAN'T BE OVERRIDEN MORE
        protected handle_insert(first: MapIterator<Key, T>, last: MapIterator<Key, T>): void override final
        {
            for (let it = first; !it.equal_to(last); it = it.next())
                this.hash_buckets_.erase(it);
        }
    }
}
@samchon samchon changed the title Accepts some grammers of C++; typedef, friend, override and final Accepts some statements of C++; typedef, friend, override and final Jul 1, 2016
@DanielRosenwasser DanielRosenwasser added the In Discussion Not yet reached consensus label Jul 1, 2016
@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Jul 1, 2016

Hey @samchon! Glad to see the enthusiasm here. One thing I'll mention is that there are existing issues for some of what you've brought up here:

I think one thing that you've mentioned is that you'd like to be able to have type alias declarations in classes, but from the use-case you're giving, I think you could perform class-namespace merging to achieve the same goal:

class Foo {
    x: Foo.Bar;
}
namespace Foo {
    export type Bar = string;
}

var abc: Foo.Bar

You can try it out in our playground.

So would it be fair to say the other issues, as well as the suggestion here, cover what you've brought up?

@samchon
Copy link
Author

samchon commented Jul 1, 2016

Wow, most of what I mentioned is almost have argued. Class inline type defitnition, there was an indirect method defining same named namespace.

The code seems something weird, but there's a solution.

namespace std
{
    namespace List
    {
        export type iterator<T> = std.ListIterator<T>;
    }
}

let list: std.List<number>;
let it: std.List.iterator<number> = list.begin();
    // IN C++, std::list<number>::iterator it = list.begni();

@DanielRosenwasser Thanks for your replying.

@mhegazy mhegazy added Duplicate An existing issue was already created and removed In Discussion Not yet reached consensus labels Jul 12, 2016
@mhegazy
Copy link
Contributor

mhegazy commented Jul 12, 2016

The type alias definition in classes was initially proposed in #7061.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 12, 2016

looks like all the proposals are already covered in other issues. closing to limit noise.

@mhegazy mhegazy closed this as completed Jul 12, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants