可变 opIndex 覆盖
Variadic opIndex Override
按照我之前的 ,我现在无法使用可变参数覆盖 opIndex。我尝试了多种方法(甚至是 hack-ish 方法)但无济于事。
我用来生成标识符字符串的代码
static string array_decl(D...)(string identifier, D dimensions)
{
static if(dimensions.length == 0)
{
return identifier;
}
else
{
return array_decl(identifier ~ "[" ~ to!(string)(dimensions[0]) ~ "]", dimensions[1..$]);
}
}
我的 opIndex 覆盖是什么样的:
T opIndex(D...)(D indices)
{
mixin("return " ~ array_decl("Data", indices) ~ ";");
}
失败:
./inheritance.d(81): Error: tuple D is used as a type
./inheritance.d(89): Error: template instance inheritance.array_ident!(int, int, int).array_ident.array_ident!(_param_2, _param_3) error instantiating
./inheritance.d(112): instantiated from here: array_ident!(int, int, int)
./inheritance.d(174): instantiated from here: opIndex!(int, int, int)
./inheritance.d(112): Error: CTFE failed because of previous errors in array_ident
./inheritance.d(112): Error: argument to mixin must be a string, not ("return " ~ array_ident("Data", _param_0, _param_1, _param_2) ~ ";") of type string
问题是如何(或是否可能)针对这种情况实施 opIndex 运算符。
我认为 mixins 是可行的方法,因为我只需要生成一个格式为:
的字符串
type[index0][index1]...[indexN] Data
用于 opIndex 重载。
显然这是不可能的,因为传递给 opIndex 的元组在编译时不可访问。我提出的一些解决方案(根据 Adam D. Ruppe 的建议):
1。 硬编码数组访问
使用编译时条件来索引数组,有点难看,可以访问的维度数量取决于实现的条件数量。
T opIndex(D...)(D indices)
{
static if(indices.length == 1)
{
return Data[indices[0]];
}
static if(indices.length == 2)
{
return Data[indices[0]][indices[1]];
}
static if(indices.length == 3)
{
return Data[indices[0]][indices[1]][indices[2]];
}
static if(indices.length == 4)
{
return Data[indices[0]][indices[1]][indices[2]][indices[3]];
}
}
2。 指针
唯一的其他方法是将数组转换为指针然后使用偏移量。计算偏移量,然后用于索引指针。
能够在 运行 时访问模板参数:
struct Vector_MultiDim(T, D...)
{
enum dimensions = [D];
static const size_t DimCount = D.length;
... Other members here
}
计算偏移量的函数(每个维度的大小必须在 运行 时已知):
size_t GetIndex(size_t[] indices)
{
size_t index;
for(size_t i = 0; i < DimCount; i++)
{
size_t factor = 1;
for(size_t j = i + 1; j < DimCount; j++)
{
factor *= dimensions[j];
}
index += indices[i] * factor;
}
return index;
}
opIndex 覆盖:
T opIndex(D...)(D indices)
{
T* arr = cast(T*)Data;
return arr[GetIndex([indices])];
}
按照我之前的
我用来生成标识符字符串的代码
static string array_decl(D...)(string identifier, D dimensions)
{
static if(dimensions.length == 0)
{
return identifier;
}
else
{
return array_decl(identifier ~ "[" ~ to!(string)(dimensions[0]) ~ "]", dimensions[1..$]);
}
}
我的 opIndex 覆盖是什么样的:
T opIndex(D...)(D indices)
{
mixin("return " ~ array_decl("Data", indices) ~ ";");
}
失败:
./inheritance.d(81): Error: tuple D is used as a type
./inheritance.d(89): Error: template instance inheritance.array_ident!(int, int, int).array_ident.array_ident!(_param_2, _param_3) error instantiating
./inheritance.d(112): instantiated from here: array_ident!(int, int, int)
./inheritance.d(174): instantiated from here: opIndex!(int, int, int)
./inheritance.d(112): Error: CTFE failed because of previous errors in array_ident
./inheritance.d(112): Error: argument to mixin must be a string, not ("return " ~ array_ident("Data", _param_0, _param_1, _param_2) ~ ";") of type string
问题是如何(或是否可能)针对这种情况实施 opIndex 运算符。
我认为 mixins 是可行的方法,因为我只需要生成一个格式为:
的字符串type[index0][index1]...[indexN] Data
用于 opIndex 重载。
显然这是不可能的,因为传递给 opIndex 的元组在编译时不可访问。我提出的一些解决方案(根据 Adam D. Ruppe 的建议):
1。 硬编码数组访问
使用编译时条件来索引数组,有点难看,可以访问的维度数量取决于实现的条件数量。
T opIndex(D...)(D indices)
{
static if(indices.length == 1)
{
return Data[indices[0]];
}
static if(indices.length == 2)
{
return Data[indices[0]][indices[1]];
}
static if(indices.length == 3)
{
return Data[indices[0]][indices[1]][indices[2]];
}
static if(indices.length == 4)
{
return Data[indices[0]][indices[1]][indices[2]][indices[3]];
}
}
2。 指针
唯一的其他方法是将数组转换为指针然后使用偏移量。计算偏移量,然后用于索引指针。
能够在 运行 时访问模板参数:
struct Vector_MultiDim(T, D...)
{
enum dimensions = [D];
static const size_t DimCount = D.length;
... Other members here
}
计算偏移量的函数(每个维度的大小必须在 运行 时已知):
size_t GetIndex(size_t[] indices)
{
size_t index;
for(size_t i = 0; i < DimCount; i++)
{
size_t factor = 1;
for(size_t j = i + 1; j < DimCount; j++)
{
factor *= dimensions[j];
}
index += indices[i] * factor;
}
return index;
}
opIndex 覆盖:
T opIndex(D...)(D indices)
{
T* arr = cast(T*)Data;
return arr[GetIndex([indices])];
}