Jump to page: 1 2 3
Thread overview
Inline Structs/Named Instances of Anonymous Structs
Sep 24
Clouudy
Sep 24
Clouudy
Sep 24
claptrap
Sep 25
Clouudy
Sep 25
Clouudy
Sep 27
Clouudy
6 days ago
Clouudy
Sep 26
Hipreme
6 days ago
Clouudy
Sep 26
Ben Jones
6 days ago
Clouudy
6 days ago
Paul Backus
6 days ago
Dennis
6 days ago
Nick Treleaven
6 days ago
Juraj
September 24

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;

    void print() const {
        std::cout << "Point: (" << point.x << ", " << point.y << ")\n";
    }
};

int main() {
    Container c;
    c.point.x = 10;
    c.point.y = 20;
    c.print();
}

In D, the only way to approximate this is to define a type and then instantiate an instance of it within the struct/class:

struct Container {
    struct Point {
        int x;
        int y;
    }

    Point point;
}

This approximation is superfluous; why specify a type that is never meant to be used by users? When nested data structures become larger and larger, this type of declare-and-instantiate pattern becomes an annoyance to write, and hard to read (as the type is separated from the declaration).

Named instances of anonymous structs allow for less complexity, less verbosity, and less ambiguity over intent. The information about the variable is right next to the instantiation, and the code clearly communicates that point is simply a nested group within container, not an individual type that can/should be used on its own.

Since structs don't end with semicolons in D, a different syntax must be used. I believe that prefixing the struct with the inline keyword is the best fit:

struct Container {
    inline struct point {
        int x;
        int y;
    }
}

This doesn't add any extra keywords, and I believe it makes it clean that the struct is a single instance that is declared in the enclosing scope.

September 24

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

This doesn't add any extra keywords, and I believe it makes it clean that the struct is a single instance that is declared in the enclosing scope.

clear*

September 24

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>
struct Container {
    inline struct point {
        int x;
        int y;
    }
}

This doesn't add any extra keywords, and I believe it makes it clean that the struct is a single instance that is declared in the enclosing scope.

Why not just do this?

int point_x;
int point_y;

September 25

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;

[...]

I don't think this is a feature that has positive ROI. This is ugly, but...

struct Container {
    private struct Point { // private means users can't use it directly
        int x;
        int y;
    } Point point; // no newline, and an "extra" `Point` compared to the proposal

Alternatives include string/template mixins.

September 25

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;

    void print() const {
        std::cout << "Point: (" << point.x << ", " << point.y << ")\n";
    }
};

int main() {
    Container c;
    c.point.x = 10;
    c.point.y = 20;
    c.print();
}

In D, the only way to approximate this is to define a type and then instantiate an instance of it within the struct/class:

struct Container {
    struct Point {
        int x;
        int y;
    }

    Point point;
}

This approximation is superfluous; why specify a type that is never meant to be used by users? When nested data structures become larger and larger, this type of declare-and-instantiate pattern becomes an annoyance to write, and hard to read (as the type is separated from the declaration).

Named instances of anonymous structs allow for less complexity, less verbosity, and less ambiguity over intent. The information about the variable is right next to the instantiation, and the code clearly communicates that point is simply a nested group within container, not an individual type that can/should be used on its own.

Since structs don't end with semicolons in D, a different syntax must be used. I believe that prefixing the struct with the inline keyword is the best fit:

struct Container {
    inline struct point {
        int x;
        int y;
    }
}

This doesn't add any extra keywords, and I believe it makes it clean that the struct is a single instance that is declared in the enclosing scope.

In D, inline isn’t a keyword. Also, consider modifiers such as private or static that you might want to apply to the newly defined variables, but not the struct itself. How would you do that?

The syntax I’d say works better is:

struct Container {
    struct private static Point point1, point2 {
        int x;
        int y;
    }
}

Essentially, if after struct there’s one identifier before the opening brace, that’s a simple struct definition. Alternatively, there could be a variable declaration with attributes and whatnot, followed by the declaration block defining the struct; then, the identifier of the type of those variables is the name of the struct being defined.

I think it could be implemented by a lowering in the parser if we wanted it cheap. However, it doesn’t really mix and match. Consider making Point a struct template: Where would the template parameters even go?

I’m agree with Átila: It’s not great code. It does two different things at once, and the workaround is not only easy, but arguably better code.

September 25

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;
};

In D, you can do this with a tuple:

import std.typecons: Tuple;

struct Container {
    Tuple!(int, "x", int, "y") point;
}
September 25

On Thursday, 25 September 2025 at 09:08:34 UTC, Atila Neves wrote:

>

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;

[...]

I don't think this is a feature that has positive ROI. This is ugly, but...

struct Container {
    private struct Point { // private means users can't use it directly
        int x;
        int y;
    } Point point; // no newline, and an "extra" `Point` compared to the proposal

Alternatives include string/template mixins.

In my opinion, I think that anything that makes things clearer is something that should be at the very least looked into as a proposal. Because ven with the private struct Point method you outlined, maintainers can still get confused about whether the Point type is meant to be used multiple times. Of course if it's discovered that it's too complex to implement or gets changed along the way then yes, I would agree about the ROI being unjustifiable. But we could at least try to investigate whether that's the case.

I can tell you that from my personal experience that I did find myself wishing for this feature on one project, and that Steven also talked about adding a similar feature at DConf before as well. So at least some people think there's a problem, even if my solution isn't the best one.

September 25

On Thursday, 25 September 2025 at 13:21:59 UTC, Quirin Schroll wrote:

>

In D, inline isn’t a keyword.

I've apparently just experienced the Mandela effect because I could have sworn that it was. But apparently I just got confused with C/C++ after messing with building gcc for too long.

>

The syntax I’d say works better is:

struct Container {
    struct private static Point point1, point2 {
        int x;
        int y;
    }
}

Essentially, if after struct there’s one identifier before the opening brace, that’s a simple struct definition. Alternatively, there could be a variable declaration with attributes and whatnot, followed by the declaration block defining the struct; then, the identifier of the type of those variables is the name of the struct being defined.

I think it could be implemented by a lowering in the parser if we wanted it cheap. However, it doesn’t really mix and match. Consider making Point a struct template: Where would the template parameters even go?

I think that you're heading in the right direction, but I don't necessarily think that you need the type if it's just a singleton. It may be useful to include it optionally for reflection purposes though.

I would be satisfied with something similar like this, with the extra modifiers either before or after the struct keyword, whatever is easier to implement:

struct Container {
    struct point1 {
        int x;
        int y;
    }
}
September 25

On Thursday, 25 September 2025 at 13:34:15 UTC, Paul Backus wrote:

>

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

C++ allows you to define named instances of anonymous structs and classes:

struct Container {
    struct {
        int x;
        int y;
    } point;
};

In D, you can do this with a tuple:

import std.typecons: Tuple;

struct Container {
    Tuple!(int, "x", int, "y") point;
}

Yes, but a) it's a terrible way to specify a struct, and b) it's a heck of a lot more compile time to process.

Note that we have anonymous classes for new expressions.

I think the idea is sound and useful, I'm not sure about the syntax. In fact, the syntax is the most difficult part to figure out.

As for just being able to put a struct definition wherever you need a type, this gives a lot more power for modeling than using DSL definitions like tuple.

I talked about this kind of wishlist feature in my dconf online 2022 talk: https://youtu.be/GFvh6Hbc-3k?t=1730

-Steve

September 26

On Thursday, 25 September 2025 at 22:11:50 UTC, Steven Schveighoffer wrote:

>

On Thursday, 25 September 2025 at 13:34:15 UTC, Paul Backus wrote:

>

On Wednesday, 24 September 2025 at 02:58:53 UTC, Clouudy wrote:

>

[...]

In D, you can do this with a tuple:

import std.typecons: Tuple;

struct Container {
    Tuple!(int, "x", int, "y") point;
}

Yes, but a) it's a terrible way to specify a struct, and b) it's a heck of a lot more compile time to process.

Note that we have anonymous classes for new expressions.

I think the idea is sound and useful, I'm not sure about the syntax. In fact, the syntax is the most difficult part to figure out.

As for just being able to put a struct definition wherever you need a type, this gives a lot more power for modeling than using DSL definitions like tuple.

I talked about this kind of wishlist feature in my dconf online 2022 talk: https://youtu.be/GFvh6Hbc-3k?t=1730

-Steve

I believe that feature is really useful. And those kind of unreachable structures could have their typeinfo elided, further making the binary slimmer.

« First   ‹ Prev
1 2 3