检查类型是否是模板的实例化

时间:2010-12-29 19:29:41

标签: templates constraints d

我有像

这样的结构

struct RGBA (T) {/* ... */}
struct BMPFile (DataT) if (is(DataT == RGBA)) {/* ... */}

is(DataT == RGBA)无效,因为DataT是一种类型而RGBA是一种模板。相反,我需要检查类型是否是模板的实例化,以便声明file类似


BMPFile!(RGBA!ushort) file;

在评论中@FeepingCreature显示


    struct RGBA(T) {
        alias void isRGBAStruct;
    }
    struct BMPFile (DataT) if (is(DataT.isRGBAStruct)) {}

虽然为了工作但我没有alias void isRGBAStruct的提示,这似乎是一个黑客。希望std.traits能够涵盖这一点。

3 个答案:

答案 0 :(得分:6)

我认为你正试图过度具体。我处理这个问题的方法是允许DataT的任何类型,只要它实现我需要的任何接口。

我认为,在D2标准库中完成此操作的方法是使用IsIntegral这样的模板来测试类型的各种属性。

例如,假设您对DataT的要求是您可以finangle。你可以写:

template IsAppropriate(DataT)
{
    enum IsAppropriate = is(typeof( { DataT d; d.finangle(); }() ));
}

带上一点盐:我没有测试过,但我相信这是基本模式。如果你不熟悉上面的内容,它正在做的是检查给定的匿名函数是否编译;它只能在finangle DataT。{/ p> {{1}}时进行编译

答案 1 :(得分:2)

这完全来自记忆,所以请稍等一些。

首先,那些结构需要实体,你应该从中得到解析错误。其次,BMPFile上的模板约束不起作用,因为它试图比较RGBA!ushort(一种类型)和RGBA(一种模板),它们是不同类型的东西。最后我检查了(并且已经有一段时间了)没有干净的方法来检查类型是否是给定模板的实例化。

答案 2 :(得分:2)

一旦模板被实例化,它就是它自己的野兽。如果您有

等结构
struct RGBA(T)
{
}

您不能直接测试该结构的特定实例化是否是该结构的瞬时。您可以测试像is(RGBA!int == RGBA!int)或者是(RGBA!T == RGBA!int)`(如果你有T),但没有办法询问泛型类型是否是RGBA的实例化。

原因主要是因为RGBA 不是类型。它是一种类型的模板。在实例化模板之前不存在任何类型,并且模板的实例化与模板的任何其他瞬时没有任何关系。 RGBA!int与RGBA!float无关。由于模板约束和模板特化等,这两种类型可能完全不同。 e.g。

struct RGBA(T : int)
{
    float a;
    double b;
    bool[] c;
}

struct RGBA(T : float)
{
    @property int w() const pure nothrow
    {
        return 2;
    }
}

现在,如果你愿意稍微限制自己,你可以玩游戏。诀窍是你需要一种方法来获得用于实例化RGBA的T.所以,这样的事情会起作用:

import std.traits;

struct RGBA(T)
{
}

struct BMPFile(DataT, T)
    if(is(DataT == RGBA!T) &&
       IsIntegral!T)
{
}

现在,这有一个限制,即T是一个整数类型,可能是你想要的,也可能不是。 isFloatingPoint!() is(T == bool)std.traits中的一些函数以及__traits中的特征都可以正常工作。因此,如果您对T的含义有所了解,可以添加适当的约束来检查T的类型。

现在,如果你做了类似

的事情
struct BMPFile(DataT, T)
    if(is(DataT == RGBA!T))

然后总是第二次给出类型,这也会起作用:BMPFile(RGBA!int, int)(虽然我猜你真的不想这样做)。

另一种选择是,如果你知道RGBA上有一个返回T或者T的函数,你可以测试DataT上是否存在该函数,并使用特征来获取类型。 e.g。

import std.traits;

struct RGBA(T)
{
    T func() { return T.init;}
}

struct BMPFile(DataT, T = ReturnType!(DataT.func))
    if(is(DataT == RGBA!T))
{
}

然而,当你传递一些没有func函数的东西时,它的错误消息会变得非常难看,并且如果从RGBA实例化的类型以外的类型设置为匹配模板,那么'将尝试并实例化它,这可能会或可能不会工作,但在任何一种情况下可能都不是你想要的。

所以,它归结为目前没有任何方法可以直接做你想做的事情,但是如果你玩一些游戏,你可以得到一些有效的东西。本质上,它归结为找到一种方法来定义模板,以便您可以访问用于实例化第一个模板的参数(在本例中为RGBA),以便您可以测试类型({{ 1}})给第二个模板(DataT)是该类型的实例化(BMPFile)。如果你能得到RGBA!T,那么你可以测试T