On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote:

here is something for you to play with:


import std.stdio;

enum CallAllowed0;
enum CallAllowed1;

struct S {
  @CallAllowed0 void foo () { writeln("foo()"); }
  @CallAllowed1 void foo (int n) { writeln("foo(", n, ")"); }
}


bool hasGoodMethod(string methodName, UDA, C, Args...) () {
  import std.traits: hasUDA;
  bool res = false;
  alias Identity(T...) = T[0];
  foreach (string mem; __traits(allMembers, C)) {
    static if (mem == methodName) {
      static if (is(typeof(__traits(getMember, C, mem)))) {
        alias mx = Identity!(__traits(getMember, C, mem));
        foreach (auto t; __traits(getOverloads, C, mem)) {
          static if (hasUDA!(t, UDA)) {
static if (is(typeof((Args args) { auto dg = &t; dg(args); }))) {
              res = true;
              break;
            }
          }
        }
      }
    }
  }
  return res;
}

auto doit(string methodName, UDA, C, Args...) (C c, Args args) {
  static if (hasGoodMethod!(methodName, UDA, C, Args)) {
    mixin("return c."~methodName~"(args);");
  } else {
static assert(0, "can't call method '"~methodName~"' in type "~C.stringof);
  }
}


void main () {
  S s;
  version(v0) {
    s.doit!("foo", CallAllowed0)(42);
  } else version(v1) {
    s.doit!("foo", CallAllowed1)(42);
  } else version(v2) {
    s.doit!("foo", CallAllowed0)();
  } else version(v3) {
    s.doit!("foo", CallAllowed1)();
  } else {
    static assert(0, "version?");
  }
}


% rdmd -version=v0 z02.d
z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(55): instantiated from here: doit!("foo", CallAllowed0, S, int)

% rdmd -version=v1 z02.d
foo(42)

% rdmd -version=v2 z02.d
foo()

% rdmd -version=v3 z02.d
z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(61): instantiated from here: doit!("foo", CallAllowed1, S)

Reply via email to