Проверьте, является ли Alias ​​шаблоном в D 2.0 - PullRequest
6 голосов
/ 30 марта 2011

Как проверить, является ли псевдоним шаблоном в 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 ]

5 голосов
/ 31 марта 2011

Это проходит все, кроме 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));

Если выуверены, что шаблон не будет иметь аргумента по умолчанию, содержащего "...!(..." Я думаю, что он безопасен для использования.

1 голос
/ 30 марта 2011

Этот код применяет адрес оператора '&', который не применим к шаблонам, для идентификации идентификатора шаблона.

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
1 голос
/ 30 марта 2011

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 );
1 голос
/ 30 марта 2011
template isTemplate(alias T, Args...)
{
    enum bool isTemplate = __traits(compiles, T!(Args));
}

это также накладывает дополнительное ограничение - это должен быть шаблон, который может быть создан с заданными аргументами.

...