Тест если псевдоним шаблона в D 2.0
Как проверить, является ли псевдоним шаблоном в D 2.0?
template isTemplate(alias T)
{
enum bool isTemplate = ???;
}
обновление:
Он должен работать так:
struct S(T)
{
int opCall() { return 0; }
int opUnary(string s)() if (s == "-") { return 0; }
}
pragma(msg, isTemplate!(S)); //Should print true
pragma(msg, isTemplate!(S!(int))); //Should print false
pragma(msg, isTemplate!((S!(int)).opCall)); //Should print false
pragma(msg, isTemplate!((S!(int)).opUnary)); //Should print true
Для справки, вещи, которые не работы:
вы не можете использовать любое выражение, как
T!(...)
потому что вы не знаете, что поставить на место эллипсов.ты не можешь сказать
&T
потому что это также не работает, если вам просто дали простое старое имя типа.
4 ответов
это проходит все, кроме 2 тестов, которые я перечислил в другого ответа
import std.algorithm : startsWith, canFind;
template isTemplate(alias B) {
enum isTemplate = !__traits(compiles, {auto x=B;}) // excludes values
&& !__traits(compiles, {B x;}) // excludes types
&& __traits(compiles, {alias B x;}) // excludes instance members
&& !B.stringof.startsWith("module ", "package ") // excludes modules
&& !B.stringof.canFind("!("); // excludes instantiated templates
}
2 теста, которые потерпели неудачу, как:
struct Inner2(string U="!(") {}
static assert(isTemplate(Inner2));
Если вы уверены, что шаблон не будет иметь аргумент по умолчанию, содержащий "...!(..."
Я думаю, что это безопасно для использования.
template isTemplate(alias T, Args...)
{
enum bool isTemplate = __traits(compiles, T!(Args));
}
это также ставит дополнительное ограничение - это должен быть шаблон, который может быть создан с заданными аргументами.
этот код применяет адрес оператора'&', который не применим к шаблонам, для идентификации идентификатора шаблона.
struct S (T) {
int a;
int foo () () {}
int xyz (A) (A a) {}
void bar (T t) {}
}
void main () {
S!(int) s;
foreach (m; __traits(allMembers, S!(int)))
writeln (m, " is template: ", !__traits(compiles, mixin("&s." ~ m)));
}
вывод:
a is template: false
foo is template: true
xyz is template: true
bar is template: false
A шаблон параметра может принимать многие вещи: переменные, пользовательские типы, модули, шаблоны и литералы.
, Так что isTemplate
должны пройти следующие тесты:
struct FooS(T) {
struct Inner {}
struct Inner2(string U="!(") {}
int func(U)() { return 0; }
int bar;
}
FooS!int foo;
class FooC { int x; }
union FooU { int x;}
enum FooE { x }
interface FooI { int x(); }
template FooT(T) {
struct Inner {}
struct Inner2(string U="!(") {}
int func(U)() { return 0; }
int bar;
}
static assert(! isTemplate!0 );
static assert(! isTemplate!"0" );
static assert(! isTemplate!0.0f );
static assert(! isTemplate!'0' );
static assert(! isTemplate!'!' );
static assert(! isTemplate!"module std.stdio" );
static assert(! isTemplate!null );
static assert(! isTemplate!true );
static assert(! isTemplate!__FILE__ );
static assert(! isTemplate!__LINE__ );
static assert(! isTemplate!([]) );
static assert( isTemplate!FooS );
static assert(! isTemplate!(FooS!int) );
static assert( isTemplate!(FooS!int.func) );
static assert(! isTemplate!(FooS!int.func!float) );
static assert(! isTemplate!(FooS!int.bar) );
static assert(! isTemplate!(FooS!int.Inner) );
static assert( isTemplate!(FooS!int.Inner2) );
static assert(! isTemplate!(FooS!int.Inner2!"?") );
static assert( isTemplate!FooT );
static assert(! isTemplate!(FooT!int) );
static assert( isTemplate!(FooT!int.func) );
static assert(! isTemplate!(FooT!int.func!float) );
static assert(! isTemplate!(FooT!int.bar) );
static assert(! isTemplate!(FooT!int.Inner) );
static assert( isTemplate!(FooT!int.Inner2) );
static assert(! isTemplate!(FooT!int.Inner2!"?") );
static assert(! isTemplate!foo );
static assert( isTemplate!(foo.func) );
static assert( isTemplate!isTemplate );
static assert(! isTemplate!(isTemplate!isTemplate) );
static assert(! isTemplate!FooC );
static assert(! isTemplate!FooU );
static assert(! isTemplate!FooE );
static assert(! isTemplate!FooI );
static assert(! isTemplate!((int x){return x;}) );
static assert( isTemplate!(std.stdio.writefln) );
static assert(! isTemplate!(std.stdio) );
static assert(! isTemplate!std );