Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
October 19, 2012 Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
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? Thank you all for your time, Michael |
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael | 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
|
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael | On 10/18/2012 08:44 PM, Michael wrote: > auto fib(T = int)() if (isIntLike!T) { > struct Fib { > T a, b; // ... > 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? Explicit conversion works: return Fib(T(0), T(1)); Ali |
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, October 18, 2012 20:55:12 Ali Çehreli wrote:
> Explicit conversion works:
>
> return Fib(T(0), T(1));
Except that that won't work for int or other built-in types, because they lack constructors. What you need is std.conv.to.
- Jonathan M Davis
|
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Jonathan M Davis:
> Except that that won't work for int or other built-in types, because they lack constructors.
Isn't it possible to modify D and add constructors to built-in types?
int(10)
Bye,
bearophile
|
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Friday, October 19, 2012 10:59:07 bearophile wrote:
> Jonathan M Davis:
> > Except that that won't work for int or other built-in types, because they lack constructors.
>
> Isn't it possible to modify D and add constructors to built-in types?
>
> int(10)
Of course, it would be possible. Whether Walter would agree to though, I have no idea. C++ allows it only because it allows you to use the cast operator in reverse - i.e. int(10) is identical to (int)10 - though it wouldn't need it in the OP's example, because it would do the implicit conversion.
What I'd like to see even more is the ability to do
auto i = new int(10);
which would be particularly useful with immutable, since right now, it's impossible to create an immutable pointer to int with a value of anything other than 0 without casting.
- Jonathan M Davis
|
October 19, 2012 Re: Implicit Conversions in Struct Construction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Friday, 19 October 2012 at 09:36:14 UTC, Jonathan M Davis wrote:
> On Friday, October 19, 2012 10:59:07 bearophile wrote:
>> Jonathan M Davis:
>> > Except that that won't work for int or other built-in types,
>> > because they lack constructors.
>>
>> Isn't it possible to modify D and add constructors to built-in
>> types?
>>
>> int(10)
>
> Of course, it would be possible. Whether Walter would agree to though, I have
> no idea. C++ allows it only because it allows you to use the cast operator in
> reverse - i.e. int(10) is identical to (int)10 - though it wouldn't need it in
> the OP's example, because it would do the implicit conversion.
>
> What I'd like to see even more is the ability to do
>
> auto i = new int(10);
>
> which would be particularly useful with immutable, since right now, it's
> impossible to create an immutable pointer to int with a value of anything
> other than 0 without casting.
>
> - Jonathan M Davis
You can use the array.ptr "trick" (or exploit):
void main()
{
immutable int a = 5;
immutable(int)* p1 = [a].ptr;
immutable(int*) p2 = [a].ptr;
}
That said, it is ugly as sin, and "new int(5)" should definitely supported.
Same thing with structs actually, which can be "agglomerate constructed", or "default copy constructed" : If you can write "auto a = T(x);" you should be able to write "auto p = new T(x)";
|
Copyright © 1999-2021 by the D Language Foundation