我正在为 D 中的线性代数库实现一个多维张量,这基本上是我为基类的目标:
class Tensor( T_scalar, T_dimensions ..., int T_storageOrder = StorageOrder.columnMajor )
{
}
在这个想法中,用户可以通过模板参数定义张量的特征,因此我可以在编译时尽可能多地推导出东西,有点像 Eigen 所做的。不幸的是,编译器对该定义不太满意,并触发了如下错误:
Tensor(T_scalar,T_args...,int T_storageOrder = StorageOrder.columnMajor) template tuple parameter must be last one
我不太确定为什么会有这个限制,但我最终做了我认为是黑客的事情......基本上,将 StorageOrder 定义为枚举允许我检查模板元组参数的最后一个参数是否匹配一个枚举中的值,如果是这样,我可以使用它来设置该张量的 StorageOrder 的值,否则我使用默认值设置它。
enum StorageOrder : int
{
columnMajor = -1,
rowMajor = -2
}
class Tensor( T_scalar, T_args ... )
{
private:
alias TensorTraits!( T_scalar, T_args ) traits;
alias traits.dimensions T_dimensions;
alias traits.storageOrder T_storageOrder;
}
struct TensorTraits( T_scalar, T_args ... )
if ( areTemplateParametersValid!( T_scalar, T_args )() )
{
static immutable auto dimensions = mixin( extractDataFromTemplateTupleParameter.dimensions );
static immutable int storageOrder = extractDataFromTemplateTupleParameter.storageOrder;
private:
static auto extractDataFromTemplateTupleParameter()
{
Tuple!( string, "dimensions", int, "storageOrder" ) templateTupleParameterData;
static if ( T_args[$ - 1] == StorageOrder.columnMajor || T_args[$ - 1] == StorageOrder.rowMajor )
{
alias TypeTuple!( T_args[0 .. $ - 1] ) dimensionsTuple;
templateTupleParameterData.storageOrder = T_args[$ - 1];
}
else
{
alias TypeTuple!( T_args ) dimensionsTuple;
templateTupleParameterData.storageOrder = StorageOrder.columnMajor;
}
static assert( dimensionsTuple.length > 0,
"No dimensions have been defined." );
foreach ( dimension; dimensionsTuple )
{
static assert( isIntegral!( typeof( dimension ) ),
"Dimensions sizes needs to be defined as integrals." );
static assert( dimension >= 0,
"Dimensions sizes cannot be negative." );
}
templateTupleParameterData.dimensions = dimensionsTuple.stringof;
return templateTupleParameterData;
}
}
static bool areTemplateParametersValid( T_scalar, T_args ... )()
{
static assert( isNumeric!( T_scalar ),
"The 'T_scalar' template argument is not a numeric type." );
static assert( T_args.length > 0,
"No dimensions have been defined." );
return true;
}
由于我刚开始使用 D,并且由于我对这个 hack 不太确定,我想知道这对你们来说是否听起来不错,或者是否有更好的方法来处理这个问题?