guard condition for a callable thingy, with THESE arguments

2016-05-14 Thread cy via Digitalmars-d-learn
I take callbacks on occasion, and I don't really care if they're 
a delegate, or a function, or a callable object, and I can assert 
that in a template:


void foo(Callable)(Callable callback) if(isSomeFunction!Callable 
|| isCallable!Callable) {

 ...
}

That works, but it doesn't show you what arguments the callable 
will take, or how many, or what its return type should be.


You can of course read the body of the `foo` function to spy out 
where the text "callable(" might be, but it'd be really nice if I 
could put that information in my guard condition somehow. What I 
want is something like this.


bool default_callback(int foo, string bar, Something baz) {
 ...
}

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,default_callback)) {

 ...
}

or

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,bool function(int,string,Something)) 
{

 ...
}

Is that possible to do? Has it already been done?


Re: guard condition for a callable thingy, with THESE arguments

2016-05-14 Thread Ann W. Griffith via Digitalmars-d-learn

On Sunday, 15 May 2016 at 01:59:15 UTC, cy wrote:
I take callbacks on occasion, and I don't really care if 
they're a delegate, or a function, or a callable object, and I 
can assert that in a template:


void foo(Callable)(Callable callback) 
if(isSomeFunction!Callable || isCallable!Callable) {

 ...
}

That works, but it doesn't show you what arguments the callable 
will take, or how many, or what its return type should be.


You can of course read the body of the `foo` function to spy 
out where the text "callable(" might be, but it'd be really 
nice if I could put that information in my guard condition 
somehow. What I want is something like this.


bool default_callback(int foo, string bar, Something baz) {
 ...
}

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,default_callback)) {

 ...
}

or

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,bool 
function(int,string,Something)) {

 ...
}

Is that possible to do? Has it already been done?


use "Parameters" in the constraint or make a template that you 
can reeuse.



import std.traits;

alias Model = void function(int, string);

void foo(Callable)(Callable callback)
if(is(Parameters!Callable == Parameters!Model)) {}

void main(string[] args)
{
static void right(int,string){}
static assert(__traits(compiles, foo(&right)));
static void wrong(int){}
static assert(!__traits(compiles, foo(&wrong)));
}



Re: guard condition for a callable thingy, with THESE arguments

2016-05-15 Thread cy via Digitalmars-d-learn

On Sunday, 15 May 2016 at 02:12:38 UTC, Ann W. Griffith wrote:
use "Parameters" in the constraint or make a template that you 
can reeuse.


This is what I've got going so far. Using static asserts to have 
clearer errors when an incorrect callback is supplied. I'm not... 
sure storage class is important.


import std.traits: isSomeFunction, isCallable,
  ParameterTypeTuple, ParameterStorageClassTuple, ReturnType,
  isDelegate;

import std.stdio;

template isCompatibleFunction(alias Src, alias Dest) {
 static assert(isSomeFunction!Src || isCallable!Src,
   "Source is not callable");
 static assert(isSomeFunction!Dest || isCallable!Dest,
   "Destination is not callable");

  static assert(is(ParameterTypeTuple!Src == 
ParameterTypeTuple!Dest),

"Type Tuples differ");
  pragma(msg,ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest);
  static assert(ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest,
"Storage classes differ");
  static assert(is(ReturnType!Src == ReturnType!Dest),
"Return type differs");
  immutable bool isCompatibleFunction = true;
}


bool function_callback(string a) {
  return true;
}

template foobar(Callable) 
if(isCompatibleFunction!(function_callback,Callable)) {

  template foobar(Callable c) {
immutable bool foobar = c("foo");
  }
}

void main() {
  bool result = true;
  bool delegate_callback(string a) {
return result;
  }
  bool delegate(string) dg = &delegate_callback;
  static assert(isDelegate!dg);
  static assert(isCompatibleFunction!(function_callback, 
delegate_callback));

  struct Derp {
static bool opCall(string a) {
  return true;
}
bool opCall(string a) {
  return false;
}
bool member(string a) {
  return true;
}
  };
  static 
assert(isCompatibleFunction!(function_callback,Derp.init.member));
  static 
assert(isCompatibleFunction!(function_callback,Derp.init));

  static assert(isCompatibleFunction!(function_callback,Derp));
  static assert(isCompatibleFunction!(delegate_callback,Derp));
  if(foobar!function_callback) {
writeln("foo");
  } else {
writeln("bar");
  }
  writeln("derp");
}



Re: guard condition for a callable thingy, with THESE arguments

2016-05-15 Thread Ann W. Griffith via Digitalmars-d-learn

On Sunday, 15 May 2016 at 07:22:57 UTC, cy wrote:

On Sunday, 15 May 2016 at 02:12:38 UTC, Ann W. Griffith wrote:
use "Parameters" in the constraint or make a template that you 
can reeuse.


This is what I've got going so far. Using static asserts to 
have clearer errors when an incorrect callback is supplied. I'm 
not... sure storage class is important.


It could be important, especially "ref" and "out" that could lead 
to UB if not checked, without compile error. "shared" also but 
when supplied, invalid callback will not compile.