Check for presence of function

2014-03-23 Thread Steve Teale
What's the cool/idiomatic D way to test at compile time if a 
struct has a member function with a particular signature? Along 
the lines of:


struct Unrelated
{
   ...
}

template isSomething(T)
{
enum bool isSomething = is(typeof(
(inout int = 0)
{
   T???; // has a function void doSomething(Unrelated* up);
   // etc
}));
}

struct Thingie
{
   ...
}

static assert(isSomething!(Thingie));

Thanks
Steve


Re: Check for presence of function

2014-03-23 Thread Philippe Sigaud
On Sun, Mar 23, 2014 at 1:40 PM, Steve Teale
steve.te...@britseyeview.com wrote:
 What's the cool/idiomatic D way to test at compile time if a struct has a
 member function with a particular signature? Along the lines of:

 struct Unrelated
 {
...
 }

 template isSomething(T)
 {
 enum bool isSomething = is(typeof(
 (inout int = 0)
 {
T???; // has a function void doSomething(Unrelated* up);
// etc
 }));
 }

 struct Thingie
 {
...
 }

 static assert(isSomething!(Thingie));

You can use __traits(compiles, /* some code */), like this:


struct Unrelated {}

template isSomething(T)
{
enum bool isSomething = __traits(compiles,
{
   Unrelated* up;
   T.init.doSomething(up);
}
);
}

struct Thingie
{
void doSomething(Unrelated* up) {}
}

void main()
{
pragma(msg, isSomething!Thingie); // true
pragma(msg, isSomething!Unrelated); // false
pragma(msg, isSomething!int); // false
}


Re: Check for presence of function

2014-03-23 Thread Dicebot

template isSomething(T)
{
enum isSomething =
is(typeof(__traits(getMember, T, doSomething)) == function)
	  is(typeof(__traits(getMember, T, doSomething)) : void 
function(Unrelated*));

}


Re: Check for presence of function

2014-03-23 Thread Philippe Sigaud
Ideally, the alias part of the grammar could be extended and
isSomething simplified as:

alias isSomething(T) = __traits(compiles,
{
   Unrelated* up;
   T.init.doSomething(up);
}
);

But this is not accepted by the grammar right now, because of __traits()


Re: Check for presence of function

2014-03-23 Thread Adam D. Ruppe

On Sunday, 23 March 2014 at 12:57:36 UTC, Philippe Sigaud wrote:
But this is not accepted by the grammar right now, because of 
__traits()


That's easy enough to work around with an alias helper:

alias helper(alias T) = T;


alias isSomething(T) = alias!(__traits(compiles,
{
   Unrelated* up;
   T.init.doSomething(up);
}
));


Re: Check for presence of function

2014-03-23 Thread Adam D. Ruppe

On Sunday, 23 March 2014 at 13:00:09 UTC, Adam D. Ruppe wrote:

alias isSomething(T) = alias!(__traits(compiles,


oops that should say helper! not alias!


Re: Check for presence of function

2014-03-23 Thread Adam D. Ruppe

On Sunday, 23 March 2014 at 12:53:39 UTC, Dicebot wrote:

template isSomething(T)
{
enum isSomething =
is(typeof(__traits(getMember, T, doSomething)) == function)
	  is(typeof(__traits(getMember, T, doSomething)) : void 
function(Unrelated*));

}


That won't necessarily work in the presence of overloaded 
functions since getMember only gets one of them.


You could though do this:

template isSomething(T) {
bool checker() {
foreach(overload; __traits(getOverloads, T, 
doSomething))
static if(is(typeof(overload) == void 
function(Unrelated*)))

   return true;
return false;
}
enum isSomething = checker();
}

getOverloads returns an empty tuple for non-functions so you 
don't even have to check that ahead of time.


Re: Check for presence of function

2014-03-23 Thread Dicebot

On Sunday, 23 March 2014 at 13:03:07 UTC, Adam D. Ruppe wrote:
That won't necessarily work in the presence of overloaded 
functions since getMember only gets one of them.


Yeah, forgot to add this part, will make end result a bit less 
pretty indeed.


Updated version with overloads will be more reliable than 
proposed duck-typing version as it won't false trigger in 
presence of alias this or opDispatch. Though Steve may actually 
want it to trigger, I don't know.


Re: Check for presence of function

2014-03-23 Thread Andrej Mitrovic
On 3/23/14, Philippe Sigaud philippe.sig...@gmail.com wrote:
 But this is not accepted by the grammar right now, because of __traits()

Pretty sure it's because you're using 'alias' instead of 'enum'. This works:

-
enum isSomething(T) = __traits(compiles,
{
   int up;
   T.init.doSomething(up);
}
);

void main()
{
static struct S { void doSomething(int); }
static struct X { void doSomething(string); }
static assert(isSomething!S);
static assert(!isSomething!X);
}
-


Re: Check for presence of function

2014-03-23 Thread Philippe Sigaud
On Sun, Mar 23, 2014 at 2:50 PM, Andrej Mitrovic
andrej.mitrov...@gmail.com wrote:

 Pretty sure it's because you're using 'alias' instead of 'enum'. This works:

Oww! For years, D told me I couldn't use __traits in an easy way like
this. I'll have to teach me out of it, and use enum :-) Damn, but
using enum is quite natural too. Thanks Andrej.

Now, if only __traits could be beautified somewhat... I mean: everyone
is using it, it's time to make it more palatable.


Re: Check for presence of function

2014-03-23 Thread Steve Teale

On Sunday, 23 March 2014 at 13:23:58 UTC, Dicebot wrote:

On Sunday, 23 March 2014 at 13:03:07 UTC, Adam D. Ruppe wrote:
That won't necessarily work in the presence of overloaded 
functions since getMember only gets one of them.


Yeah, forgot to add this part, will make end result a bit less 
pretty indeed.


Updated version with overloads will be more reliable than 
proposed duck-typing version as it won't false trigger in 
presence of alias this or opDispatch. Though Steve may 
actually want it to trigger, I don't know.


DB,

In my particular question, I would not have wanted, or cared if 
alias this was triggered, but that was a narrow view.


My primary point is that there should be something in the wiki to 
help old-fashioned programmers like me to change from an OOP 
style that is not 100% necessary, to a struct based  style that 
should be quicker, but that allows the compiler to help me, or 
other contributors to the same project, to write add-on 
components that are at least checked at compile time.


So what I'm after really, is how do you do interfaces outside of 
OOP.


Std.range does that sort of thing in what seem to me to be very 
simple cases, but there is a lot of scope for different scenarios.


Thanks for your answer
Steve



Re: Check for presence of function

2014-03-23 Thread Andrej Mitrovic
On 3/23/14, Philippe Sigaud philippe.sig...@gmail.com wrote:
 Now, if only __traits could be beautified somewhat... I mean: everyone
 is using it, it's time to make it more palatable.

That's what std.traits is for, to hide the __traits and is() uglyness.