templates - 模板比较在模板体内发生变化

标签 templates metaprogramming d

我有一个结构体 Foo!T 和一个对任意两个 Foo!T 进行操作的函数。 我希望声明这样一个函数

void fun(U)(U a, U b) if (is(U : Foo!T, T...)) { }

但是,事实证明我可以将其声明为

void fun(U)(U a, U b) if (is(U : Foo)) { }

仅当我在 Foo内部声明它。

例如:

struct Foo(T) { 
    void fun1(U)(U b) if (is(U : Foo)) { } 
}

void fun2(U)(U a, U b) if (is(U : Foo)) { }

unittest {
    Foo!int f;
    f.fun1(f);
    f.fun2(f);
}

以上失败,并在调用时使用struct d.Foo(T) 作为类型 有趣2。不过,fun1 没问题。

为什么约束 is(U : Foo)Foo 体内有效,但无效 外部?

Foo 体内的比较 is(U : Foo) 是否等同于 is(U : Foo!V, V...)Foo 的主体之外?

最佳答案

在模板类型内部,模板的名称指的是模板的特定实例化,除非明确给出了不同的实例化。例如,

struct Foo(T)
{
    pragma(msg, Foo.stringof);
}
pragma(msg, Foo.stringof);

void main()
{
    Foo!int foo1;
    Foo!string foo2;
}

打印

Foo(T)
Foo!int
Foo!string

打印的第一个编译指示是紧随模板之后的编译指示,另外两个编译指示是在实例化 Foo 时生成的。这使得当您引用它时(例如,当从成员函数返回它时),您不必在结构声明内的所有地方粘贴 Foo!T 。如果类型具有多个而不是只有一个模板参数,则这一点特别有用。但这确实意味着如果您想引用通用模板,您要么需要使用特定参数实例化它 - 例如在 Foo 内部使用 Foo!int 来引用 Foo!int,无论当前实例是什么 - 或者您需要使用点运算符表明您希望来自外部作用域的 Foo 。例如

struct Foo(T)
{
    pragma(msg, Foo.stringof);
    pragma(msg, .Foo.stringof);
}
pragma(msg, Foo.stringof);

void main()
{
    Foo!int foo1;
    Foo!string foo2;
}

打印

Foo(T)
Foo!int
Foo(T)
Foo!string
Foo(T)

因此,当在模板类型中编写诸如模板约束之类的内容时,请注意在 struct Foo(T)class Foo( T) 表示特定实例化,而不是模板本身。

另外,如果您正在专门测试 U 是否是 Foo 的实例,我建议使用 std.traits.isInstanceOf - 例如if(isInstanceOf(Foo, U))。可以说,它确实应该是 isInstantiationOf 而不是 isInstanceOf,但无论如何,它以比使用裸露 is 表达式更惯用的方式完成这项工作。

关于templates - 模板比较在模板体内发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36222313/

相关文章:

c++ - C++中的模板参数继承

python - 有人在 Python/其他语言中使用 meta-meta-classes/meta-meta-meta-classes 吗?

haskell - Haskell中的程序化类型注释

templates - 检查符号是否是 D 中的成员函数/字段的[指针]

c++ - 模板类的继承问题

c++:如果条件不满足,函数调用会出现编译时错误?

c++ - 无法推断返回类型的模板参数

macros - 将表达式插入到引号内的表达式中

java - 这样对于Java和C/D通信来说是一个好的设计吗?

struct - 如何在 D 中初始化全局结构数组?