Thread overview
How to construct a struct that does not explicitly define a constructor
Feb 28
Meta
Mar 01
Meta
Mar 01
user1234
February 28
struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        return Test(n, f);
    }
}

void main()
{
    Test(1, 2.0);
}

This code causes an infinite loop because the Test(n, f) inside the static opCall is interpreted as a recursive call to that same opCall function - not a call to the struct's constructor (or however this is interpreted by the compiler when there is no explicit struct/union constructor defined).

I tried doing return Test.__ctor(n, f) but it says that symbol doesn't exist. Is there any way to explicitly call the struct's constructor so it doesn't cause an infinitely recursive call to opCall?

March 01

On Friday, 28 February 2025 at 23:31:23 UTC, Meta wrote:

>
struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        return Test(n, f);
    }
}

void main()
{
    Test(1, 2.0);
}

This code causes an infinite loop because the Test(n, f) inside the static opCall is interpreted as a recursive call to that same opCall function - not a call to the struct's constructor (or however this is interpreted by the compiler when there is no explicit struct/union constructor defined).

I tried doing return Test.__ctor(n, f) but it says that symbol doesn't exist. Is there any way to explicitly call the struct's constructor so it doesn't cause an infinitely recursive call to opCall?

You can't call the constructor because there isn't one.

What you can do is use curly-brace initialization syntax:

struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        Test result = { n, f };
        return result;
    }
}

void main()
{
    auto test = Test(1, 2.0);
    assert(test.n == 1);
    assert(test.f == 2.0);
}
March 01

On Saturday, 1 March 2025 at 00:47:20 UTC, Paul Backus wrote:

>

What you can do is use curly-brace initialization syntax:

struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        Test result = { n, f };
        return result;
    }
}

void main()
{
    auto test = Test(1, 2.0);
    assert(test.n == 1);
    assert(test.f == 2.0);
}

Thanks, I forgot about that syntax. Another question I have is if there's a way to do this inline:

struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        //return {n, f};            Error
        //return Test {n, f};       Error
        //return {n: n, f: f};      Error
        //return Test {n: n, f: f}; Error
    }
}

void main()
{
    auto test = Test(1, 2.0);
    assert(test.n == 1);
    assert(test.f == 2.0);
}
March 01

On Saturday, 1 March 2025 at 02:19:55 UTC, Meta wrote:

>

On Saturday, 1 March 2025 at 00:47:20 UTC, Paul Backus wrote:

>

What you can do is use curly-brace initialization syntax:

Thanks, I forgot about that syntax. Another question I have is if there's a way to do this inline:

No, there's no way to do it inline.

Really, the ideal solution here would be to get rid of your static opCall overload (for example, by turning it into a regular static method instead).

March 01

On Saturday, 1 March 2025 at 02:19:55 UTC, Meta wrote:

>

Thanks, I forgot about that syntax. Another question I have is if there's a way to do this inline:

struct Test
{
    int n;
    float f;

    static Test opCall(int n, float f)
    {
        //return {n, f};            Error
        //return Test {n, f};       Error
        //return {n: n, f: f};      Error
        //return Test {n: n, f: f}; Error
    }
}

void main()
{
    auto test = Test(1, 2.0);
    assert(test.n == 1);
    assert(test.f == 2.0);
}

As you've been said, that does not work ATM but that is something that I expect to work from day one when D will have tuples

struct Test
{
    int n;
    double f;
    static Test opCall(int n, float f)
    {
        return (0,0.1);
    }
}

because the tuple-expression (0,0.1) is explicitly convertible to Test, based on the concept of "structural typing".

March 01

On Saturday, 1 March 2025 at 03:13:55 UTC, user1234 wrote:

>

because the tuple-expression (0,0.1) is explicitly convertible to Test, based on the concept of "structural typing".

Even if D has tuples, I highly doubt that it will have this kind of implicit conversion from tuples to structs. D is generally very conservative about what implicit conversions it allows, especially conversions to and from user-defined types (like structs and classes).