Jump to page: 1 2
Thread overview
Function overloading concern
Mar 09, 2006
Sean Kelly
Mar 09, 2006
Sean Kelly
Mar 09, 2006
Carlos Santander
Mar 09, 2006
Sean Kelly
Mar 09, 2006
Sean Kelly
Mar 10, 2006
Carlos Santander
Mar 10, 2006
Sean Kelly
Mar 10, 2006
Walter Bright
Mar 10, 2006
Mike Capp
Mar 10, 2006
Sean Kelly
Mar 10, 2006
Walter Bright
Mar 10, 2006
Mike Capp
Mar 11, 2006
Bruno Medeiros
Mar 10, 2006
Walter Bright
Mar 10, 2006
Sean Kelly
Mar 10, 2006
Walter Bright
Mar 10, 2006
Bob W
Mar 09, 2006
Derek Parnell
Mar 10, 2006
Walter Bright
March 09, 2006
While I appreciate the simple overloading rules in D, the recent template improvements have me wondering how to solve cases where fully qualifying names is impossible.  Here's an example using plain old functions:

Module A:

    module a;

    void swap( inout int i1, inout int i2 )
    {
        int t = i1; i1 = i2; i2 = t;
    }

Module B:

    module b;

    struct S {}

    void swap( inout S s1, inout S s2 )
    {
        S t = s1; s1 = s2; s2 = t;
    }

Main:

    import a;
    import b;

    template func( T )
    {
        void func( inout T t1, inout T t2 )
        {
            swap( t1, t2 );
        }
    }

    void main()
    {
        int i = 1, j = 2;
        func( i, j );
    }

C:\code\d>dmd test a b
a.d(3): function a.swap conflicts with b.swap at b.d(5)
test.d(15): template instance test.func!(int) error instantiating

While I haven't run up against this situation yet, I can see it being an obstacle for large projects.  How would I resolve something like this? And I expect the overloading rules will be the same for template functions as they are for normal functions?  Finally, is there a more D-oriented approach that might address this without language changes?

I suppose one language change that might help would be to support the externally defined method syntax for primitives, so func could be rewritten as:

    template func( T )
    {
        void func( inout T t1, inout T t2 )
        {
            t1.swap( t2 );
        }
    }

and the specialized swap for struct S could be placed within its own scope.  However, this still doesn't address all situations, and I'm not entirely certain that it wouldn't introduce new overloading problems where none existed before.


Sean
March 09, 2006
I mulled this over a bit more, and I think the existing rules will work so long as template code is carefully designed with it in mind.  For example, where a template might rely on another overloaded template in C++, it might be prudent to parameterize it in D.  And with classes as reference types in D, there's a much smaller need for specialized swap functions.  My only remaining concern is traits templates in D, as they basically rely on cross-module overloading.  But perhaps this is something best sorted out by experimentation--DTL will likely have to deal with it sooner or later in any case ;-)

Sean
March 09, 2006
Sean Kelly escribió:
> While I appreciate the simple overloading rules in D, the recent template improvements have me wondering how to solve cases where fully qualifying names is impossible.  Here's an example using plain old functions:
> 
> Module A:
> 
>     module a;
> 
>     void swap( inout int i1, inout int i2 )
>     {
>         int t = i1; i1 = i2; i2 = t;
>     }
> 
> Module B:
> 
>     module b;
> 
>     struct S {}
> 
>     void swap( inout S s1, inout S s2 )
>     {
>         S t = s1; s1 = s2; s2 = t;
>     }
> 
> Main:
> 
>     import a;
>     import b;
> 
>     template func( T )
>     {
>         void func( inout T t1, inout T t2 )
>         {
>             swap( t1, t2 );
>         }
>     }
> 
>     void main()
>     {
>         int i = 1, j = 2;
>         func( i, j );
>     }
> 
> C:\code\d>dmd test a b
> a.d(3): function a.swap conflicts with b.swap at b.d(5)
> test.d(15): template instance test.func!(int) error instantiating
> 
> While I haven't run up against this situation yet, I can see it being an obstacle for large projects.  How would I resolve something like this? And I expect the overloading rules will be the same for template functions as they are for normal functions?  Finally, is there a more D-oriented approach that might address this without language changes?
> 
> I suppose one language change that might help would be to support the externally defined method syntax for primitives, so func could be rewritten as:
> 
>     template func( T )
>     {
>         void func( inout T t1, inout T t2 )
>         {
>             t1.swap( t2 );
>         }
>     }
> 
> and the specialized swap for struct S could be placed within its own scope.  However, this still doesn't address all situations, and I'm not entirely certain that it wouldn't introduce new overloading problems where none existed before.
> 
> 
> Sean

Does this work?

    import a;
    import b;

    alias a.swap swap;
    alias b.swap swap;

    template func( T )
    {
        void func( inout T t1, inout T t2 )
        {
            swap( t1, t2 );
        }
    }

    void main()
    {
        int i = 1, j = 2;
        func( i, j );
    }

-- 
Carlos Santander Bernal
March 09, 2006
Carlos Santander wrote:
> 
> Does this work?
> 
>     import a;
>     import b;
> 
>     alias a.swap swap;
>     alias b.swap swap;

It does.  alias is just too darn flexible for its own good :-)


Sean
March 09, 2006
Sean Kelly wrote:
> Carlos Santander wrote:
>>
>> Does this work?
>>
>>     import a;
>>     import b;
>>
>>     alias a.swap swap;
>>     alias b.swap swap;
> 
> It does.  alias is just too darn flexible for its own good :-)

By the way, the more complex C++ examples don't work in D anyway, because D is module-based.  For example, it's more likely func would be defined in a third module like so:

Module C:

    module c;
    import b; // let's say b is the default implementation

    template func( T )
    {
        void func( inout T t1, inout T t2 )
        {
            swap( t1, t2 );
        }
    }

Main:

    import a;
    import c;

    void main()
    {
        int i = 1, j = 2;
        func( s, t );
    }

However, this doesn't work in D even without overloading.  So perhaps it's not much of an issue here anyway.


Sean
March 09, 2006
On Thu, 09 Mar 2006 13:36:25 -0800, Sean Kelly wrote:

> Carlos Santander wrote:
>> 
>> Does this work?
>> 
>>     import a;
>>     import b;
>> 
>>     alias a.swap swap;
>>     alias b.swap swap;
> 
> It does.  alias is just too darn flexible for its own good :-)
> 
However, this is exactly one of the reasons that alias was invented by Walter - to explicitly disambiguate identifiers that reside in different modules.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
10/03/2006 9:20:29 AM
March 10, 2006
Sean Kelly escribió:
> 
> By the way, the more complex C++ examples don't work in D anyway, because D is module-based.  For example, it's more likely func would be defined in a third module like so:
> 
> Module C:
> 
>     module c;
>     import b; // let's say b is the default implementation
> 
>     template func( T )
>     {
>         void func( inout T t1, inout T t2 )
>         {
>             swap( t1, t2 );
>         }
>     }
> 
> Main:
> 
>     import a;
>     import c;
> 
>     void main()
>     {
>         int i = 1, j = 2;
>         func( s, t );
>     }
> 
> However, this doesn't work in D even without overloading.  So perhaps it's not much of an issue here anyway.
> 
> 
> Sean

This one, I don't understand. I don't have DMD to try the code, but I think the call sequence would be something like:

main -> c.func -> b.swap

The main module imports a, but it's never used.

The only thing that I can think of is that you want c.func to use a.swap because it was imported in main, but it doesn't make much sense (for me, anyway) because c never knew about a. I don't know if C++ allows that, but I would say it's not a very good design. There should be another way. IMHO.

-- 
Carlos Santander Bernal
March 10, 2006
Carlos Santander wrote:
> Sean Kelly escribió:
>>
>> By the way, the more complex C++ examples don't work in D anyway, because D is module-based.  For example, it's more likely func would be defined in a third module like so:
>>
>> Module C:
>>
>>     module c;
>>     import b; // let's say b is the default implementation
>>
>>     template func( T )
>>     {
>>         void func( inout T t1, inout T t2 )
>>         {
>>             swap( t1, t2 );
>>         }
>>     }
>>
>> Main:
>>
>>     import a;
>>     import c;
>>
>>     void main()
>>     {
>>         int i = 1, j = 2;
>>         func( s, t );
>>     }
>>
>> However, this doesn't work in D even without overloading.  So perhaps it's not much of an issue here anyway.
>>
>>
>> Sean
> 
> This one, I don't understand. I don't have DMD to try the code, but I think the call sequence would be something like:
> 
> main -> c.func -> b.swap
> 
> The main module imports a, but it's never used.

The above example doesn't really make sense in D but it's quite common in C++, whose current import mechanism is little more than a structured copy/paste during preprocessing (recall that module A defines the overload that Main wants to be used by module C).  But this is semantically meaningless in D, which was my only point--that perhaps C++ overload resolution really isn't necessary in D after all.

> The only thing that I can think of is that you want c.func to use a.swap because it was imported in main, but it doesn't make much sense (for me, anyway) because c never knew about a. I don't know if C++ allows that, but I would say it's not a very good design. There should be another way. IMHO.

It's not a good design, but the C/C++ people are stuck with it :-) There's been a recent push to adopt a module import scheme for C++, but I think the huge mass of legacy code like the above will make the scheme very difficult to use.


Sean
March 10, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:duq74p$1aoo$1@digitaldaemon.com...
> Carlos Santander wrote:
>>
>> Does this work?
>>
>>     import a;
>>     import b;
>>
>>     alias a.swap swap;
>>     alias b.swap swap;
>
> It does.  alias is just too darn flexible for its own good :-)

Actually, alias was specifically designed so that will work. It enables one to select which groups of functions one wants to overload with, rather than doing C++ style ADL.


March 10, 2006
D doesn't allow overloading of ordinary functions with template functions. C++ does, but I don't see a compelling reason for it, and it is the source of some complicated corner cases.


« First   ‹ Prev
1 2