私は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 を使い始めたばかりで、このハックについてよくわからないので、これが皆さんにとって良いと思われるかどうか、またはこれを処理するためのより良い方法があるかどうかを知りたいです。