www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Extending library functions

reply "tn" <no email.com> writes:
Hi.

I want to extend math library functions to work with my own type. 
However, the definition for my own type seems to prevent 
automated access to the original function. How can I fix this 
unexpected behavior?

Simplified example:
--------------------
import std.math;

int exp2(int x) {
     return 1 >> x;
}

void main() {
     assert(exp2(0.0) == 1.0);              // <= why does not 
this work anymore?
     //assert(std.math.exp2(0.0) == 1.0);   // <= this works
}
--------------------
Oct 18 2012
next sibling parent reply "simendsjo" <simendsjo gmail.com> writes:
On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
 Hi.

 I want to extend math library functions to work with my own 
 type. However, the definition for my own type seems to prevent 
 automated access to the original function. How can I fix this 
 unexpected behavior?

 Simplified example:
 --------------------
 import std.math;

 int exp2(int x) {
     return 1 >> x;
 }

 void main() {
     assert(exp2(0.0) == 1.0);              // <= why does not 
 this work anymore?
     //assert(std.math.exp2(0.0) == 1.0);   // <= this works
 }
 --------------------

You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods: http://dlang.org/function.html#overload-sets alias std.math.exp2 exp2;
Oct 18 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-10-18 15:35, simendsjo wrote:

 I don't think you can overload template methods with non-template methods

You cannot. The usual workaround for this is to make the non-template method a dummy template: void foo () (int a) {} // Note the extra pair of empty parentheses But this won't work if you're not controlling the non-template method. -- /Jacob Carlborg
Oct 18 2012
prev sibling next sibling parent "tn" <no email.com> writes:
On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
 On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
 Hi.

 I want to extend math library functions to work with my own 
 type. However, the definition for my own type seems to prevent 
 automated access to the original function. How can I fix this 
 unexpected behavior?

 Simplified example:
 --------------------
 import std.math;

 int exp2(int x) {
    return 1 >> x;
 }

 void main() {
    assert(exp2(0.0) == 1.0);              // <= why does not 
 this work anymore?
    //assert(std.math.exp2(0.0) == 1.0);   // <= this works
 }
 --------------------

You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods: http://dlang.org/function.html#overload-sets alias std.math.exp2 exp2;

Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template. This still does not work: -------------------- import std.math; struct Lognum(T) { T lx; } T log(T)(Lognum!T x) { return x.lx; } alias std.math.log log; void main() { //assert(std.math.log(1.0) == 0.0); assert(log(1.0) == 0.0); Lognum!double x; x.lx = 0.0; assert(log(x) == 0.0); } --------------------
Oct 18 2012
prev sibling next sibling parent "simendsjo" <simendsjo gmail.com> writes:
On Thursday, 18 October 2012 at 12:10:17 UTC, tn wrote:
 On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
 On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
 (...)
 You need to manually add std.math.exp2 to the overload set so 
 importing external methods doesn't hijack your methods:
 http://dlang.org/function.html#overload-sets

 alias std.math.exp2 exp2;

Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template. This still does not work: -------------------- import std.math; struct Lognum(T) { T lx; } T log(T)(Lognum!T x) { return x.lx; } alias std.math.log log; void main() { //assert(std.math.log(1.0) == 0.0); assert(log(1.0) == 0.0); Lognum!double x; x.lx = 0.0; assert(log(x) == 0.0); } --------------------

I don't think you can overload template methods with non-template methods: void f(string i) {} void f(T)(T i) if (is(T == double)) {} void main(string[] args) { f(2.2); } Error: template ol.f(T) if (is(T == double)) conflicts with function ol.f at ol.d(1)
Oct 18 2012
prev sibling next sibling parent "tn" <no email.com> writes:
On Thursday, 18 October 2012 at 13:35:55 UTC, simendsjo wrote:
 On Thursday, 18 October 2012 at 12:10:17 UTC, tn wrote:
 On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
 On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
 (...)
 You need to manually add std.math.exp2 to the overload set so 
 importing external methods doesn't hijack your methods:
 http://dlang.org/function.html#overload-sets

 alias std.math.exp2 exp2;

Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template. This still does not work: -------------------- import std.math; struct Lognum(T) { T lx; } T log(T)(Lognum!T x) { return x.lx; } alias std.math.log log; void main() { //assert(std.math.log(1.0) == 0.0); assert(log(1.0) == 0.0); Lognum!double x; x.lx = 0.0; assert(log(x) == 0.0); } --------------------

I don't think you can overload template methods with non-template methods: void f(string i) {} void f(T)(T i) if (is(T == double)) {} void main(string[] args) { f(2.2); } Error: template ol.f(T) if (is(T == double)) conflicts with function ol.f at ol.d(1)

That's too bad. But why then does this work: -------------------- module a; void f(string i) {} -------------------- module b; void f(T)(T i) if (is(T == double)) {} -------------------- import a; import b; void main(string[] args) { f("asdf"); f(2.2); } --------------------
Oct 18 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
simendsjo:

 I don't think you can overload template methods with 
 non-template methods:

But maybe this will change. Bye, bearophile
Oct 18 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, October 18, 2012 16:22:17 bearophile wrote:
 simendsjo:
 I don't think you can overload template methods with

 non-template methods:


It's bug (I forget the exact bug number). TDPL says that you can do it, and as I understand it, it's simply a question of when someone is going to fix it (though I have no idea how easy it will be to fix it) and not a question of whether it'll change or not. - Jonathan M Davis
Oct 18 2012