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