D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 1860 - Heap construction of structs with args doesn't work
Summary: Heap construction of structs with args doesn't work
Status: RESOLVED WONTFIX
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: x86 Windows
: P2 enhancement
Assignee: Walter Bright
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-02-21 15:28 UTC by Bill Baxter
Modified: 2020-02-08 09:57 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Bill Baxter 2008-02-21 15:28:48 UTC
Heap construction of structs using arguments doesn't work.  It doesn't matter if there's a static opCall explicitly defined or not.

-----
struct NoOpCalls
{
    int i;
    float x;
}
struct WithOpCall
{
    static WithOpCall opCall(int _i, float _x) {
        WithOpCall R; with(R) {
            i = _i;
            x = _x;
        } return R;
    }

    int i;
    float x;
}


void main()
{
    auto stacka = NoOpCalls(2, 5.0); // ok
    auto stackb = WithOpCall(2, 5.0); // ok

    auto heapa = new NoOpCalls(2, 5.0); // error no constructor
    auto heapb = new WithOpCall(2, 5.0); // error no constructor
}
----

This seems like an oversight rather than a deliberate design decision.

You can work around by "double initializing":

   auto heapa = new NoOpCalls; *heapa = NoOpCalls(2,5.0);

But that seems unnecessarily repetitive.

Anyway, this is yet another reason why structs should have real constructors, as opposed to the static opCall hack.
Comment 1 FeepingCreature 2008-02-22 00:45:28 UTC
Try this.

import std.gc
struct heapmalloc(T) {
	static T* opCall(U...)(U u) {
		auto res = cast(T*) malloc(T.sizeof);
		(*res) = T(u);
		return res;
	}
}


struct Foo {
	int a;
	float b;
}

void main() {
	auto heapfoo = heapmalloc!(Foo)(1984, 3.14159);
}

Comment 2 FeepingCreature 2008-02-22 00:45:32 UTC
downs wrote:
> Try this.
> 
> import std.gc;
> struct heapmalloc(T) {
> 	static T* opCall(U...)(U u) {
> 		auto res = cast(T*) malloc(T.sizeof);
> 		(*res) = T(u);
> 		return res;
> 	}
> }
> 
> 
> struct Foo {
> 	int a;
> 	float b;
> }
> 
> void main() {
> 	auto heapfoo = heapmalloc!(Foo)(1984, 3.14159);
> }

Or this.

import std.gc;

T* toHeap(T)(T st) {
        auto res = cast(T*) malloc(T.sizeof);
        (*res) = st;
        return res;
}


struct Foo {
        int a;
        float b;
}

void main() { auto th = toHeap(Foo(1984, 3.1415926)); assert(th.a == 1984); }

:)

 --downs

Comment 3 FeepingCreature 2008-02-22 00:50:23 UTC
downs wrote:
> downs wrote:
>> Try this.
>>
>> import std.gc;
>> struct heapmalloc(T) {
>> 	static T* opCall(U...)(U u) {
>> 		auto res = cast(T*) malloc(T.sizeof);
>> 		(*res) = T(u);
>> 		return res;
>> 	}
>> }
>>
>>
>> struct Foo {
>> 	int a;
>> 	float b;
>> }
>>
>> void main() {
>> 	auto heapfoo = heapmalloc!(Foo)(1984, 3.14159);
>> }
> 
> Or this.
> 
> import std.gc;
> 
> T* toHeap(T)(T st) {
>         auto res = cast(T*) malloc(T.sizeof);
>         (*res) = st;
>         return res;
> }
> 
> 
> struct Foo {
>         int a;
>         float b;
> }
> 
> void main() { auto th = toHeap(Foo(1984, 3.1415926)); assert(th.a == 1984); }
> 
> :)
> 
>  --downs

Or this!

template heap() {
        import std.gc;
        typeof(this) heap() {
                auto res = cast(typeof(this)) malloc(typeof(*this).sizeof);
                (*res) = *this;
                return res;
        }
}

struct Foo {
        int a;
        float b;
        mixin heap!();
}

void main() { auto th = Foo(1984, 3.1415926).heap; assert(th.a == 1984); }

Comment 4 Walter Bright 2008-03-02 21:56:15 UTC
Marked as enhancement request.
Comment 5 Mathias LANG 2019-05-11 17:22:58 UTC
Great news everyone: struct have constructors (in D2)! D1 is retired tho.
Comment 6 Dlang Bot 2020-02-07 14:37:29 UTC
dlang/dub pull request #1872 "Fix issue 1860: Main man page does not mention subcommands" was merged into master:

- a1cb5e8fd240c794a3bd9127d3df351bf36f5946 by Geod24:
  Fix issue 1860: Main man page does not mention subcommands

https://github.com/dlang/dub/pull/1872
Comment 7 Mathias LANG 2020-02-08 09:57:33 UTC
Thanks but no thanks dlang-bot