www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to check at compile time if Default Constructor for a class

reply Bottled Gin <Gin Bottled.com> writes:
Hello Folks

When I try using TypeInfo_Class.defaultConstructor during compile 
time, I get:

 typeid(Foo).defaultConstructor is not yet implemented at 
 compile time
Is there any other way to find out at compile time if a default constructor exists for a given class? Regards - Puneet
Jan 01
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 1 January 2016 at 15:25:32 UTC, Bottled Gin wrote:
 When I try using TypeInfo_Class.defaultConstructor during 
 compile time, I get:
You might be able to just do `static if(__traits(compiles, new YourClass()))` and if it returns true then figure it does.
Jan 01
parent reply Bottled Gin <Gin Bottled.com> writes:
 You might be able to just do `static if(__traits(compiles, new 
 YourClass()))` and if it returns true then figure it does.
That gives me a false positive if a defined constructor has default value for all its arguments.
Jan 01
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 1 January 2016 at 15:55:53 UTC, Bottled Gin wrote:
 That gives me a false positive if a defined constructor has 
 default value for all its arguments.
I thought that counted as a default constructor... But if not, you could also try this on for size: template HasDefaultConstructor(Class) { bool helper() { foreach(overload; __traits(getOverloads, Class, "__ctor")) { static if(__traits(compiles, { Class function() ctor = &overload; })) return true; } return false; } enum HasDefaultConstructor = helper(); } The helper loops through all the overloads looking for one that is assignable to a zero-arg pointer - meaning it matches the default signature, ignoring default params. Then it just returns if it found one.
Jan 01
parent reply Basile B. <b2.temp gmx.com> writes:
On Friday, 1 January 2016 at 16:13:47 UTC, Adam D. Ruppe wrote:
 On Friday, 1 January 2016 at 15:55:53 UTC, Bottled Gin wrote:
 That gives me a false positive if a defined constructor has
The helper loops through all the overloads looking for one that is assignable to a zero-arg pointer - meaning it matches the default signature, ignoring default params. Then it just returns if it found one.
Why not just checking that a ctor has no parameter ? ~~~~~~ template HasDefaultConstructor(Class) { bool helper() { bool result; foreach(overload; __traits(getOverloads, Class, "__ctor")) { auto fun = &overload; import std.traits: Parameters; static if((Parameters!fun).length == 0) result = true; } return result; } enum HasDefaultConstructor = helper(); } ~~~~~~
Jan 01
parent Bottled Gin <Gin Bottled.com> writes:
Thanks Basile/Adam. The templates that you provided work for me.
Jan 01
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, 1 January 2016 at 15:55:53 UTC, Bottled Gin wrote:
 You might be able to just do `static if(__traits(compiles, new 
 YourClass()))` and if it returns true then figure it does.
That gives me a false positive if a defined constructor has default value for all its arguments.
And how is that not a default constructor then? What semantic difference is there between this() { this(defValue); } this(T t) { ... } and this(T t = defValue) { ... } The only way that I can think of that it could even matter would be if you were trying to take the address of the constructor, which would be a rather odd thing to do. It seems like saying that a constructor with all default arguments is not a default constructor is a distinction without meaning. What are you doing that you would care? - Jonathan M Davis
Jan 01
parent reply Bottled Gin <Gin Bottled.com> writes:
 It seems like saying that a constructor with all default 
 arguments is not a default constructor is a distinction without 
 meaning. What are you doing that you would care?
The Object.factory does not seem to consider a constructor with default arguments as a defaultConstructor. Consider the following code snippet. It works only when I uncomment line 3. module foo; // 1 class Foo { // 2 // this() {} // 3 this(int n=0) {} // 4 } // 5 void main() { // 6 auto obj = Object.factory("foo.Foo"); // 7 assert(obj !is null); // 8 auto foo = cast(Foo) obj; // 9 assert(foo !is null); // 10 } // 11
Jan 01
next sibling parent reply Bottled Gin <Gin Bottled.com> writes:
I think this is related to the bug 3438 that got fixed recently.

https://issues.dlang.org/show_bug.cgi?id=3438

Regards
- Puneet
Jan 01
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, 2 January 2016 at 03:06:26 UTC, Bottled Gin wrote:
 I think this is related to the bug 3438 that got fixed recently.

 https://issues.dlang.org/show_bug.cgi?id=3438
I'd be surprised if issue# 3438 were related, though given that I'm not all that familiar with the compiler internals, I suppose that it could be. But 3438 has to do with struct constructors and should not have had any effect on classes. If it did, then it was an unintended side effect of the changes. - Jonathan M Davis
Jan 01
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, 2 January 2016 at 02:42:56 UTC, Bottled Gin wrote:
 It seems like saying that a constructor with all default 
 arguments is not a default constructor is a distinction 
 without meaning. What are you doing that you would care?
The Object.factory does not seem to consider a constructor with default arguments as a defaultConstructor. Consider the following code snippet. It works only when I uncomment line 3. module foo; // 1 class Foo { // 2 // this() {} // 3 this(int n=0) {} // 4 } // 5 void main() { // 6 auto obj = Object.factory("foo.Foo"); // 7 assert(obj !is null); // 8 auto foo = cast(Foo) obj; // 9 assert(foo !is null); // 10 } // 11
Well, I would definitely consider it a bug for the Object factory to not work with a constructor with all default arguments, though given that the default arguments are known at compile time and not runtime, I don't know if it can actually treat a constructor with all default arguments like a default constructor or not. That would depend on how it works, and I'm not familiar with its inner workings. So, you may have found a place where the distinction between a constructor with no parameters and one with all default arguments does matter much as it really shouldn't. - Jonathan M Davis
Jan 01