On Monday, 29 March 2021 at 16:31:49 UTC, Paul Backus wrote:
On Monday, 29 March 2021 at 16:20:59 UTC, Ali Çehreli wrote:
auto myFunc(F)(string name, F func)
{
// This condition could be a template constraint but they don't
  // support error messages.
  static assert (is (Parameters!func == AliasSeq!(string)),
"'func' must be a callable that takes 'string'.");
  return func(name);
}

void main() {
// One trouble with this "solution" is that for the compiler to
  // know the return type of the lambda, the parameter must be
  // declared as 'string' (in this case).
  writeln(myFunc("foo", (string a) => a ~ '.'));
}

Ali

Alternatively:

    auto myFunc(F)(string name, F func)
    {
      static assert (__traits(compiles, (string s) => func(s)),
"'func' must be a callable that takes 'string'.");
      return func(name);
    }

    void main() {
      // No need to write out the argument type
      writeln(myFunc("foo", a => a ~ '.'));
    }

You can generalize this into a helper template:

    enum bool isCallableWith(alias fun, ArgTypes...) =
      __traits(compiles, (ArgTypes args) => fun(args));

Usage:

    static assert(isCallableWith!(func, string));

------------------------------------------------------------------------

Ah that was even easier than I had made it out to be, thank you folks!

The part about needing to define the argument types to the lambda is no problem either (it was a silly transcription mistake on my end).

I actually need those argument types for later, to generate code based on them (translating D arg types -> a subset of C types, for building a translated function signature string to give to another app) so it works out =D

Much appreciated.

Reply via email to