Implicit Conversions in Struct Construction

Jonathan M Davis jmdavisProg at gmx.com
Thu Oct 18 20:54:30 PDT 2012


On Friday, October 19, 2012 05:44:10 Michael wrote:
> Hello,
>    I have been playing around with templated range. I am not quite
> sure why the following code does not work:
> 
> template isIntLike(T) {
> 	enum isIntLike = is(typeof({
> 		T t = 0;
> 		t = t+t;
> 		// More if needed
> 	}));
> }
> 
> auto fib(T = int)() if (isIntLike!T) {
> 	struct Fib {
> 		T a, b;
> 
> 		T front() {return b;}
> 		bool empty() {return false;}
> 
> 		void popFront() {
> 			T c = a+b;
> 			a = b;
> 			b = c;
> 		}
> 	}
> 	return Fib(0, 1);
> }
> 
> This code does not work if I call fib!BigInt(). The compiler
> complains that 0 cannot be implicitly converted into a BigInt. It
> is right of course, but BigInt has a constructor accepting a
> long, so shouldn't this work anyway? What is the correct way to
> write this function?

Constructors aren't implicitly called in D like they are in C++. If you have a 
function which takes a BigInt, it won't accept anything except a BigInt and 
something which implicitly converts to a BigInt (which would mean that the 
type had an alias this which converted it to BigInt). So, Fib(0, 1) will never 
work for Fib!BigInt. It would require Fib(BigInt(0), BigInt(1)), which you 
obviously can't do in generic code. However, you can use std.conv.to to do the 
conversion, so it becomes Fib(to!T(0), to!T(1)), and that should work (to will 
call the constructor if the constructor accepts the type that you're giving 
it). But if you do that, you should probably adjust isIntLike to also test 
that to!T(0) works.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list