View mode: basic / threaded / horizontal-split · Log in · Help
July 10, 2011
Implicit type conversion for function calls?
I'm trying to have this sort of code compile:

////////////////
struct Foo {
     int data;
     this(int n) {
         data = n;
     }
}

void bar(Foo f) {}

bar(3);
////////////////

Is this even possible? I believe the feature was called
opImplicitCastFrom, at some point.

Conversely, the following would also be useful:

////////////////
struct Foo {
      int data;
      this(int n) {
          data = n;
      }
}

void bar(int n) {}

Foo f;
bar(f);
////////////////

This would then be called opImplicitCastTo.

The reason I want this, is I'm trying to create templates that do what
typedef should - create a supertype, subtype, or lateral type to an
existing type.

-- 
    Simen
July 10, 2011
Re: Implicit type conversion for function calls?
Simen Kjaeraas:

> I'm trying to have this sort of code compile:
> 
> ////////////////
> struct Foo {
>       int data;
>       this(int n) {
>           data = n;
>       }
> }
> 
> void bar(Foo f) {}
> 
> bar(3);
> ////////////////
> 
> Is this even possible?

There is a uncommon syntax that allows you to do it with a class, but I don't know why structs don't work here:

class Foo {
   int data;

   this(int n) {
       data = n;
   }
}

void bar(Foo f ...) {
   assert(f.data == 3);
}

void main() {
   bar(3);
}

Bye,
bearophile
July 10, 2011
Re: Implicit type conversion for function calls?
On Sun, 10 Jul 2011 16:41:17 +0200, bearophile <bearophileHUGS@lycos.com>  
wrote:

> There is a uncommon syntax that allows you to do it with a class, but I  
> don't know why structs don't work here:
>
> class Foo {
>     int data;
>
>     this(int n) {
>         data = n;
>     }
> }
>
> void bar(Foo f ...) {
>     assert(f.data == 3);
> }
>
> void main() {
>     bar(3);
> }

Smells like a bug. But, even if that did work for structs, it is an
invasive way to do it, which opImplicitCastTo/From would not be.

For a typedef template, that's unacceptable.

-- 
  Simen
July 10, 2011
Re: Implicit type conversion for function calls?
On 7/10/11 3:29 PM, Simen Kjaeraas wrote:
> I'm trying to have this sort of code compile:
>
> ////////////////
> struct Foo {
> int data;
> this(int n) {
> data = n;
> }
> }
>
> void bar(Foo f) {}
>
> bar(3);
> ////////////////
>
> Is this even possible?

If I remember correctly, Walter said that this is a deliberate 
limitation the last time I asked (when implementing my units of 
measurement library). I think the intention is to avoid confusion about 
what is actually going on behind the scenes, like it is possible in C++ 
with implicitly called constructors.

David
July 10, 2011
Re: Implicit type conversion for function calls?
On Sunday 10 July 2011 20:47:04 David Nadlinger wrote:
> On 7/10/11 3:29 PM, Simen Kjaeraas wrote:
> > I'm trying to have this sort of code compile:
> > 
> > ////////////////
> > struct Foo {
> > int data;
> > this(int n) {
> > data = n;
> > }
> > }
> > 
> > void bar(Foo f) {}
> > 
> > bar(3);
> > ////////////////
> > 
> > Is this even possible?
> 
> If I remember correctly, Walter said that this is a deliberate
> limitation the last time I asked (when implementing my units of
> measurement library). I think the intention is to avoid confusion about
> what is actually going on behind the scenes, like it is possible in C++
> with implicitly called constructors.

Yes. In C++, the compiler will do up to 3 conversions for you, so you can end 
up calling a very different function than you might have intended to. It's 
usually not a problem, but it can definitely lead to issues and can effectively 
be a form of function hijacking. So, D forces you to do the conversion 
yourself by constructing a temporary of the appropriate type or doing a cast 
or whatnot. I expect that if there is anything that allows you to get away 
with it (such as what Bearophile did), it's a bug.

The only exceptions to this are things which would allow for an implicit cast 
(such as alias this). There has been talk from time to time of adding an 
opImplicitCast, which would allow you to define when this sort of thing coudl 
happen (at least when you've defined the type being passed in), but it's never 
been added to the language, and I think that alias this is pretty much 
supposed to solve that problem, so I don't expect that it ever will.

- Jonathan M Davis
July 10, 2011
Re: Implicit type conversion for function calls?
On Sun, 10 Jul 2011 21:39:54 +0200, Jonathan M Davis <jmdavisProg@gmx.com>  
wrote:

> On Sunday 10 July 2011 20:47:04 David Nadlinger wrote:
>> On 7/10/11 3:29 PM, Simen Kjaeraas wrote:
>> > I'm trying to have this sort of code compile:
>> >
>> > ////////////////
>> > struct Foo {
>> > int data;
>> > this(int n) {
>> > data = n;
>> > }
>> > }
>> >
>> > void bar(Foo f) {}
>> >
>> > bar(3);
>> > ////////////////
>> >
>> > Is this even possible?
>>
>> If I remember correctly, Walter said that this is a deliberate
>> limitation the last time I asked (when implementing my units of
>> measurement library). I think the intention is to avoid confusion about
>> what is actually going on behind the scenes, like it is possible in C++
>> with implicitly called constructors.
>
> Yes. In C++, the compiler will do up to 3 conversions for you, so you  
> can end
> up calling a very different function than you might have intended to.  
> It's
> usually not a problem, but it can definitely lead to issues and can  
> effectively
> be a form of function hijacking. So, D forces you to do the conversion
> yourself by constructing a temporary of the appropriate type or doing a  
> cast
> or whatnot. I expect that if there is anything that allows you to get  
> away
> with it (such as what Bearophile did), it's a bug.
>
> The only exceptions to this are things which would allow for an implicit  
> cast
> (such as alias this). There has been talk from time to time of adding an
> opImplicitCast, which would allow you to define when this sort of thing  
> coudl
> happen (at least when you've defined the type being passed in), but it's  
> never
> been added to the language, and I think that alias this is pretty much
> supposed to solve that problem, so I don't expect that it ever will.

So then the idea of creating typedef as has been described before (and as
was part of the argument for removing the feature) as a template is
impossible.

-- 
  Simen
July 10, 2011
Re: Implicit type conversion for function calls?
On Sunday 10 July 2011 22:15:05 Simen Kjaeraas wrote:
> On Sun, 10 Jul 2011 21:39:54 +0200, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > On Sunday 10 July 2011 20:47:04 David Nadlinger wrote:
> >> On 7/10/11 3:29 PM, Simen Kjaeraas wrote:
> >> > I'm trying to have this sort of code compile:
> >> > 
> >> > ////////////////
> >> > struct Foo {
> >> > int data;
> >> > this(int n) {
> >> > data = n;
> >> > }
> >> > }
> >> > 
> >> > void bar(Foo f) {}
> >> > 
> >> > bar(3);
> >> > ////////////////
> >> > 
> >> > Is this even possible?
> >> 
> >> If I remember correctly, Walter said that this is a deliberate
> >> limitation the last time I asked (when implementing my units of
> >> measurement library). I think the intention is to avoid confusion
> >> about
> >> what is actually going on behind the scenes, like it is possible in
> >> C++
> >> with implicitly called constructors.
> > 
> > Yes. In C++, the compiler will do up to 3 conversions for you, so you
> > can end
> > up calling a very different function than you might have intended to.
> > It's
> > usually not a problem, but it can definitely lead to issues and can
> > effectively
> > be a form of function hijacking. So, D forces you to do the conversion
> > yourself by constructing a temporary of the appropriate type or doing a
> > cast
> > or whatnot. I expect that if there is anything that allows you to get
> > away
> > with it (such as what Bearophile did), it's a bug.
> > 
> > The only exceptions to this are things which would allow for an implicit
> > cast
> > (such as alias this). There has been talk from time to time of adding an
> > opImplicitCast, which would allow you to define when this sort of thing
> > coudl
> > happen (at least when you've defined the type being passed in), but it's
> > never
> > been added to the language, and I think that alias this is pretty much
> > supposed to solve that problem, so I don't expect that it ever will.
> 
> So then the idea of creating typedef as has been described before (and as
> was part of the argument for removing the feature) as a template is
> impossible.

Well, if you can do it with alias this, then it's possible. If not, then it 
probably isn't. But I don't know what opImplicitCast would give you if alias 
this doesn't (particularly if alias this is working properly; the current 
implementation is buggy enough that whether it works now or not doesn't 
necessarily mean much). I really don't know what would be required to get a 
TypeDef template working properly though. I don't really see any need for such 
a beast personally, so I haven't really looked into it.

Regardless, implicitly casting from one type to another is typically verboten 
in D in order to avoid bugs. There are exceptions - particularly with built-in 
types - and alias this is intended to give you the ability to have implicit 
casting on some level, but it's definitely something that causes hijacking in 
C++, so D went for a stricter route which generally disallows it.

- Jonathan M Davis
July 11, 2011
Re: Implicit type conversion for function calls?
On Sun, 10 Jul 2011 22:30:34 +0200, Jonathan M Davis <jmdavisProg@gmx.com>  
wrote:

> Well, if you can do it with alias this, then it's possible. If not, then  
> it
> probably isn't. But I don't know what opImplicitCast would give you if  
> alias
> this doesn't (particularly if alias this is working properly; the current
> implementation is buggy enough that whether it works now or not doesn't
> necessarily mean much). I really don't know what would be required to  
> get a
> TypeDef template working properly though. I don't really see any need  
> for such
> a beast personally, so I haven't really looked into it.

Basically, four types of typedef were outlined:

Supertype!T - You may pass T to a function requiring Supertype!T,
  and may assign a T to a Supertype!T, but not vice versa.

Subtype!T - You may pass a Subtype!T to a function requiring T,
  and may assign a Subtype!T to a T, but not vice versa.

Lateraltype!T - Behaves like a T in most ways, but cannot pass a T
  to a function expecting a Lateraltype!T, nor vice versa.

alias - Yeah, you know the one.

All of these have their uses, and currently only alias is in the
language.

-- 
  Simen
Top | Discussion index | About this forum | D home