Как только шаблон создан, он становится его собственным зверем. Если у вас есть структура, такая как
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)
.