From 2b8471fe34b07c4f1ae4aed479d6d1f631881435 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 24 Mar 2019 21:59:29 +0100 Subject: [PATCH] Add meta.trait.hasFunctionAttributes --- meta/tanya/meta/metafunction.d | 4 +-- meta/tanya/meta/trait.d | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/meta/tanya/meta/metafunction.d b/meta/tanya/meta/metafunction.d index 8ccafbc..3f8d0e4 100644 --- a/meta/tanya/meta/metafunction.d +++ b/meta/tanya/meta/metafunction.d @@ -1779,7 +1779,7 @@ if (T.length == 2) } /** - * Attaces a numeric index to each element from $(D_PARAM Args). + * Attaches a numeric index to each element from $(D_PARAM Args). * * $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s) * consisting of the index of each element and the element itself. @@ -1817,7 +1817,7 @@ template EnumerateFrom(size_t start, Args...) } /** - * Attaces a numeric index to each element from $(D_PARAM Args). + * Attaches a numeric index to each element from $(D_PARAM Args). * * $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s) * consisting of the index of each element and the element itself. diff --git a/meta/tanya/meta/trait.d b/meta/tanya/meta/trait.d index ae83f24..db9b847 100644 --- a/meta/tanya/meta/trait.d +++ b/meta/tanya/meta/trait.d @@ -2257,6 +2257,61 @@ if (isCallable!F) static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0); } +/** + * Determines whether a function has attribute. + * + * This template should get at least two arguments: the function itself and the + * attributes it should be tested for. If more than one attribute is given, + * $(D_PSYMBOL hasFunctionAttributes) evaluates to $(D_KEYWORD true) if all of + * them are present. The attributes should be $(D_PSYMBOL FunctionAttribute) + * members. + * + * Params: + * Args = The function and attributes. + * + * Returns: + * + * See_Also: $(D_PSYMBOL FunctionAttribute). + */ +template hasFunctionAttributes(Args...) +if (Args.length > 1 + && is(typeof(Args[1]) == FunctionAttribute) + && isCallable!(Args[0]) + && allSameType!(Map!(TypeOf, Args[1 .. $]))) +{ + enum uint pred(Args_...) = Args_[0] | Args_[1]; + + template Reduce(Args_...) + { + static if (Args_.length == 1) + { + enum uint Reduce = Args_[0]; + } + else + { + enum uint Reduce = Reduce!(pred!(Args_[0], Args_[1]), Args_[2 .. $]); + } + } + enum uint field = Reduce!(0, Args[1 .. $]); + enum hasFunctionAttributes = (functionAttributes!(Args[0]) & field) == field; +} + +/// +@nogc nothrow pure @safe unittest +{ + static struct Range + { + @property auto front() inout + { + return 8; + } + } + static assert(hasFunctionAttributes!(Range.init.front, FunctionAttribute.inout_)); + static assert(!hasFunctionAttributes!(Range.init.front, FunctionAttribute.const_)); + static assert(!hasFunctionAttributes!(Range.init.front, + FunctionAttribute.inout_, FunctionAttribute.const_)); +} + /** * Returns a tuple with default values of the parameters to $(D_PARAM F). *