Bug 5931 – keyword new won't allow default initialization of a struct where it has a non-zero argument constructor
Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Mac OS X
Creation time
2011-05-05T12:08:38Z
Last change time
2018-05-05T13:15:28Z
Assigned to
No Owner
Creator
Christopher the Magnificent
Comments
Comment #0 by ultimatemacfanatic — 2011-05-05T12:08:38Z
So I need to do this:
class Tokenizer
{
File file;
this(File f)
{
File f2; // default initialized
// problem 1
this.file = new File; // should pointer to return default initialized File struct but compiler complains
*this.file = f;
// problem 2
this.file = new File(f); // this doesn't work either, notwithstanding File has a this(this) post-blitter!
}
}
unfortunately, on the line where I make the call to "new File", it gives me this error:
Error: constructor std.stdio.File.this (string name, in const(char[]) stdioOpenmode = "rb") is not callable using argument types ()
Shouldn't I be able to allocate a default-initialized struct? Or if not, shouldn't it be allow to have empty-argument struct constructors? http://www.digitalmars.com/d/2.0/struct.html says empty parameter-list constructors are not allowed for structs, but why not? Can someone explain this language decision to me and make a good argument for why it should not be changed?
when I try "new File(f)" then I get this error message:
tokenizer.d(199): Error: constructor std.stdio.File.this (string name, in const(char[]) stdioOpenmode = "rb") is not callable using argument types (File)
tokenizer.d(199): Error: cannot implicitly convert expression (file) of type File to string
It seems to me that the post-blit constructor should be called automatically when a struct is "function-called" with an instance of the same struct as the sole parameter like "new S(s_instance)" Don't you agree? You may think this is a feature request, but when functionality is a departure from what one would expect, I would tend to call that a bug instead. :-)
Comment #1 by ultimatemacfanatic — 2011-05-05T19:55:08Z
This line above (5th line or so)
> File file;
should read
File* file;
in other words, the member <file> is supposed to be a pointer to File.
Comment #2 by kennytm — 2011-05-06T01:46:03Z
Post-blit is only called when you override the whole structure, as in:
----------------------------------------
import std.stdio;
struct S {
this(this) {
writeln("postblit");
}
}
void main() {
S s;
S t;
s = t; // <-- call postblit on s.
}
----------------------------------------
Pointer-assignment will *not* call post-blit as you have not blitted (memcpy-ed) anything.
Comment #3 by ultimatemacfanatic — 2011-05-06T12:32:02Z
(In reply to comment #2)
> Post-blit is only called when you override the whole structure, as in:
>
> ----------------------------------------
> import std.stdio;
>
> struct S {
> this(this) {
> writeln("postblit");
> }
> }
>
> void main() {
> S s;
> S t;
> s = t; // <-- call postblit on s.
> }
> ----------------------------------------
>
> Pointer-assignment will *not* call post-blit as you have not blitted
> (memcpy-ed) anything.
*Shouldn't* post-blit be invokable by calling <File(file)>? Wouldn't this be a desirable behavior?
If not, how do I allocate a default-initialized File struct in the heap using <new> (so that I can follow that by overwriting the whole structure and get post-blitter to run)?
what I'm taking about is this (this is what I want to do):
////////////////////////////
import std.stdio;
struct Tokenizer
{
File* file = null;
void
initFile(File f)
{
this.file = new File; // I want to allocate a new File struct and set it to File.init -- DOESN"T WORK!
*this.file = f; // copy bits and then automatically call post-blit File.this(this)
}
}
////////////////////////////
At the line above marked "DOESN'T WORK", the compiler refuses to allocate a new default-initialized File struct. This is a problem
Comment #4 by kennytm — 2011-05-06T12:47:28Z
(In reply to comment #3)
> *Shouldn't* post-blit be invokable by calling <File(file)>? Wouldn't this be a
> desirable behavior?
>
Sorry, got distracted by the 'this.file = new File(...)' part because of your 'File file;' :).
No it should not call post-blit directly, because is possible to *declare* such a constructor. The problem is, should D define the implicitly-defined copy constructor which does:
struct S {
this(ref S s) {
this = s; // implicitly calls the postblit
}
...
}
?
[snip]
> At the line above marked "DOESN'T WORK", the compiler refuses to allocate a new
> default-initialized File struct. This is a problem
This problem is the same as issue 4249.
Comment #5 by kennytm — 2011-05-06T12:48:43Z
(In reply to comment #4)
> (In reply to comment #3)
[snip]
> > At the line above marked "DOESN'T WORK", the compiler refuses to allocate a new
> > default-initialized File struct. This is a problem
>
> This problem is the same as issue 4249.
I mean issue 4247 -.-
Comment #6 by johannes.loher — 2018-05-05T13:15:28Z
The first problem mentioned has been solved since 2.063.
The second problem is still present, error message of 2.080.0:
main.d(16): Error: none of the overloads of this are callable using argument types (File), candidates are:
/usr/include/dlang/dmd/std/stdio.d(387): std.stdio.File.this(shared(_IO_FILE)* handle, string name, uint refs = 1u, bool isPopened = false)
/usr/include/dlang/dmd/std/stdio.d(425): std.stdio.File.this(string name, const(char[]) stdioOpenmode = "rb")
/usr/include/dlang/dmd/std/stdio.d(443): std.stdio.File.__ctor(R1, R2)(R1 name) if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1))
/usr/include/dlang/dmd/std/stdio.d(451): std.stdio.File.__ctor(R1, R2)(R1 name, R2 mode) if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) && isInputRange!R2 && isSomeChar!(ElementEncodingType!R2))
The reason is in general, that you can't call postblits as if they were constructors (`File file; auto f = File(file);` also does not work).
However, it seems that postblits will probably be replaced by some form of copy constructor, so this might even resolve this issue. I will close this for now. If you really want this feature, please submit a new issue as an enhancement request.