测试别名是否是 D 2.0 中的模板

发布于 2024-10-27 15:18:28 字数 740 浏览 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,因为如果你只给出一个普通的旧类型名称,这也不起作用。

How do I test if an alias is a template in D 2.0?

template isTemplate(alias T)
{
    enum bool isTemplate = ???;
}

Update:

It should work like:

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

For reference, things that don't work:

  • You can't use any expression like T!(...) because you don't know what to put in place of the ellipses.

  • You can't say &T because that also doesn't work if you're just given a plain old type name.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

月亮坠入山谷 2024-11-03 15:18:28

这通过了除我在 另一个答案

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));

如果您确定模板不会有包含 "...!(..." 的默认参数我认为使用是安全的。

This passes all except 2 tests I have listed in the other answer

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
}

The 2 tests that have failed like:

struct Inner2(string U="!(") {}
static assert(isTemplate(Inner2));

If you are sure the template won't have a default argument containing "...!(..." I think it is safe to use.

穿透光 2024-11-03 15:18:28
template isTemplate(alias T, Args...)
{
    enum bool isTemplate = __traits(compiles, T!(Args));
}

这也带来了额外的限制 - 它必须是可以使用给定参数实例化的模板。

template isTemplate(alias T, Args...)
{
    enum bool isTemplate = __traits(compiles, T!(Args));
}

this also puts additional constraint - it must be template which can be instantiated with given arguments.

溇涏 2024-11-03 15:18:28

此代码正在应用运算符地址“&”不适用于模板,用于识别模板标识符。

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

This code is applying operator address-of '&' which is not applicable to templates, to identify template identifier.

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)));
}

output is:

a is template: false
foo is template: true
xyz is template: true
bar is template: false
万劫不复 2024-11-03 15:18:28

模板别名参数可以接受很多东西:变量、自定义类型、模块、模板和文字。

因此 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 );

A template alias parameter can accept many things: variables, custom types, modules, templates and literals.

So that isTemplate should pass the following test cases:

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 );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文