Проверьте, является ли тип экземпляром шаблона - PullRequest
4 голосов
/ 29 декабря 2010

У меня есть такие структуры, как


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 ]

6 голосов
/ 30 декабря 2010

Я думаю, вы пытаетесь быть слишком конкретным.Чтобы справиться с этим, я должен разрешить любой тип для DataT, при условии, что он реализует любой интерфейс, который мне нужен.

Способ, которым я это делаю в стандартной библиотеке D2, я считаю, состоит в том, чтобы иметь шаблонынапример, IsIntegral, которые проверяют различные свойства типа.

Например, допустим, ваше требование для DataT состоит в том, что вы можете finangle его.Вы могли бы написать:

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

Возьмите вышесказанное с крошкой соли: я не проверял это, но я считаю, что это основной шаблон.Если вы не знакомы с вышесказанным, он проверяет, компилируется ли данная анонимная функция;он может скомпилироваться, только если возможно finangle DataT.

2 голосов
/ 30 декабря 2010

Как только шаблон создан, он становится его собственным зверем. Если у вас есть структура, такая как

struct RGBA(T)
{
}

Вы не можете напрямую проверить, является ли конкретное создание этой структуры экземпляром этой структуры. Вы можете проверить что-то вроде is(RGBA!int == RGBA!int) или is (RGBA! T == RGBA! Int) `(если у вас есть T), но нет способа спросить, является ли универсальный тип экземпляром RGBA.

Причина этого, по сути, в том, что RGBA является , а не типом. Это шаблон для типа. Никакого типа не существует, пока вы не создадите экземпляр шаблона, и ни один экземпляр шаблона не имеет никакого отношения к любому другому экземпляру шаблона. RGBA! Int не имеет отношения к RGBA! Float. Благодаря шаблонным ограничениям и шаблонным специализациям и тому подобному эти два типа могут быть полностью разными. например,

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

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

Теперь есть игры, в которые вы можете играть, если хотите немного ограничить себя. Хитрость в том, что вам нужен способ получить T, который будет использоваться для создания RGBA. Итак, что-то вроде этого будет работать:

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, и использовать черты для определения типа. например,

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), чтобы можно было проверить, является ли тип (DataT) данный второй шаблон (BMPFile) является экземпляром этого типа (RGBA!T). Если вы можете получить T, тогда вы можете проверить, is(DataT == RGBA!T).

2 голосов
/ 30 декабря 2010

Это все из памяти, поэтому возьмите его с небольшим количеством соли.

Во-первых, эти структуры нуждаются в телах, вы должны получать ошибки синтаксического анализа.Во-вторых, ограничение шаблона на BMPFile не будет работать, потому что оно пытается сравнить RGBA!ushort (тип) и RGBA (шаблон), которые представляют собой разные вещи.В последний раз, когда я проверял (и это было давно), не существует чистого способа проверить, является ли тип экземпляром данного шаблона.

...