www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function hijack on selective import

reply rumbu <rumbu rumbu.ro> writes:
Is there anyway to extend an existing function to accept custom 
data types?



****************
Option 1 - global import of std.math


import std.math;

struct Custom {}

int signbit(T)(T x) if (is(T == Custom))
{
     return 0;
}

Custom c;
assert(signbit(c) == 0);
assert(signbit(-1.0) == 1);

Error: template main.signbit cannot deduce function from argument 
types !()(double), candidates are:
main.signbit(T)(T x) if (is(T == Custom))


*******************
Option 2 - selective import of std.math

import std.math : signbit;

struct Custom {}

int signbit(T)(T x) if (is(T == Custom))
{
     return 0;
}

Custom c;
assert(signbit(c) == 0);
assert(signbit(-1.0) == 1);


main.signbit called with argument types (Custom) matches both:
\..\src\phobos\std\math.d(5721):     
std.math.signbit!(Custom).signbit(Custom x)
and:
main.signbit!(Custom).signbit(Custom x)
Dec 26 2017
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
The mistake you're making is using a constraint when you should 
try a specialization:


int signbit(T:Custom)(T x)
{
     return 0;
}


That means to use this specialized function when T is Custom. 
Now, you just need to merge the overload sets:

import std.math;
alias signbit = std.math.signbit; // this merges local signbit 
with std.math.signbit


and boom it should compile and call your version.
Dec 26 2017
parent reply rumbu <rumbu rumbu.ro> writes:
On Tuesday, 26 December 2017 at 16:15:55 UTC, Adam D. Ruppe wrote:
 The mistake you're making is using a constraint when you should 
 try a specialization:


 int signbit(T:Custom)(T x)
 {
     return 0;
 }


 That means to use this specialized function when T is Custom. 
 Now, you just need to merge the overload sets:

 import std.math;
 alias signbit = std.math.signbit; // this merges local signbit 
 with std.math.signbit


 and boom it should compile and call your version.
"Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them. My opinion is that the mistake is in std.math, because std.math.signbit accepts any type instead to be constrained to float types. Actually, calling std.math.signbit with any other type than float will result in compiler error because signbit expects some float traits for the provided type: int signbit(X)(X x) nogc trusted pure nothrow { alias F = floatTraits!(X); return ((cast(ubyte *)&x)[F.SIGNPOS_BYTE] & 0x80) != 0; }
Dec 26 2017
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
 "Custom" is a templated struct. I cannot imagine all the 
 instantiations of Custom to write template specialisations for 
 each of them.
You can specialize on templated structs generically. int foo(T : Bar!(X, Y), X, Y) that kind of thing covers any case of Bar!(X,y)
Dec 26 2017
next sibling parent rumbu <rumbu rumbu.ro> writes:
On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
 On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
 "Custom" is a templated struct. I cannot imagine all the 
 instantiations of Custom to write template specialisations for 
 each of them.
You can specialize on templated structs generically. int foo(T : Bar!(X, Y), X, Y) that kind of thing covers any case of Bar!(X,y)
Thank you, Adam.
Dec 26 2017
prev sibling parent reply rumbu <rumbu rumbu.ro> writes:
On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
 On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
 "Custom" is a templated struct. I cannot imagine all the 
 instantiations of Custom to write template specialisations for 
 each of them.
You can specialize on templated structs generically. int foo(T : Bar!(X, Y), X, Y) that kind of thing covers any case of Bar!(X,y)
Even specialized, now I have another problem: std.math: int signbit(X)(X x) { ... } mylibrary: int signbit(D: Decimal!bits, int bits) { ... } ============= end user: import std.math; import mylibrary; Decimal!32 d; float f; auto y = signbit(f); //ok, call to std.math.signbit auto x = signbit(d); //error, also calls std.math.signbit
Jan 16 2018
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jan 16, 2018 at 07:14:00PM +0000, rumbu via Digitalmars-d-learn wrote:
 On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
 On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
 "Custom" is a templated struct. I cannot imagine all the
 instantiations of Custom to write template specialisations for
 each of them.
You can specialize on templated structs generically. int foo(T : Bar!(X, Y), X, Y) that kind of thing covers any case of Bar!(X,y)
Even specialized, now I have another problem: std.math: int signbit(X)(X x) { ... } mylibrary: int signbit(D: Decimal!bits, int bits) { ... } ============= end user: import std.math; import mylibrary; Decimal!32 d; float f; auto y = signbit(f); //ok, call to std.math.signbit auto x = signbit(d); //error, also calls std.math.signbit
Arguably, this is a defect in Phobos. Looking at the definition of std.math.signbit, it's obvious that it's only meant to handle built-in floating-point types, yet there are no sig constraints to that effect. Fix: https://github.com/dlang/phobos/pull/6040 T -- The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5
Jan 16 2018
parent rumbu <rumbu rumbu.ro> writes:
On Tuesday, 16 January 2018 at 20:30:43 UTC, H. S. Teoh wrote:
 On Tue, Jan 16, 2018 at 07:14:00PM +0000, rumbu via
 
 Even specialized, now I have another problem:
 
 std.math:
 
 int signbit(X)(X x) { ... }
 
 mylibrary:
 
 int signbit(D: Decimal!bits, int bits) { ... }
 
 =============
 
 end user:
 
 import std.math;
 import mylibrary;
 
 Decimal!32 d;
 float f;
 
 auto y = signbit(f); //ok, call to std.math.signbit
 auto x = signbit(d); //error, also calls std.math.signbit
Arguably, this is a defect in Phobos. Looking at the definition of std.math.signbit, it's obvious that it's only meant to handle built-in floating-point types, yet there are no sig constraints to that effect. Fix: https://github.com/dlang/phobos/pull/6040 T
Thank you for the pull request, but the list is longer :) https://issues.dlang.org/show_bug.cgi?id=18244
Jan 16 2018