In C++ we can easily detect that given type is a pointer to member function/field:
template< class T >
struct is_member_pointer : std::false_type {};
template< class T, class U >
struct is_member_pointer<T U::*> : std::true_type {};
There are no such syntax in D (I mean T U::*
). Moreover, free functions and methods have the same type:
void func();
struct S
{
int x;
void func() {}
}
static assert(is(typeof(func) == typeof(S.func)));
So, my question is: can we write in D a template which is analogous to C++-version?
template is_member_of(alias M)
{
alias T = /**/;
}
static assert(is(is_member_of!(S.func) == S));
static assert(is(is_member_of!func == void));
static assert(is(is_member_of!(S.x) == S));
Try taking the address of the function via the init
object instead:
static assert(is(typeof(&func) == typeof(&S.init.func)));
Will give:
ooo.d(9): Error: static assert: is(void function() == void delegate()) is false
The member function (unless it is static, but then it isn't really a member function) will be typed delegate
because it requires a this
object, whereas the other one will be typed function
.
That will work for the function, and you can do something similar with the variable (tip: static assert: is(typeof(& x)) is false
, but static assert(is(typeof(&S.init.x));
passes - note the .init) if you are curious about if it is an actual member, with a runtime this
requirement (that is, not static
).
I'll leave turning this information into a template check as an exercise to the reader (tip though: is(typeof(something) == delegate)
is a thing in the language...)
But, if you want to just know if there's a parent type on the symbol, there's a different way: just ask the compiler if there's a parent! OK, I confess the code is slightly longer to get the void
response your static asserts were looking for, but not much:
// identity template to hack around parser limitations
// this is common when using the __traits stuff, alas.
alias I(alias T) = T;
template is_member_of(alias M) {
// if it has a parent, return it, otherwise, return void
static if(is(I!(__traits(parent, M))))
alias is_member_of = I!(__traits(parent, M));
else
alias is_member_of = void;
}
You might furthermore check if the parent is certain things like struct or class, but really, if it exists at all it is probably what you're looking for.