関数の引数の数がテンプレートパラメーターに依存するように、整数のテンプレートパラメーターを使用してテンプレートクラスの関数を定義したいと思います。次に例を示します。
template< class Coord, int dim >
class Point {
Coord mCoords[ dim ];
public:
void Set( /* I want exactly dim Coord arguments here. */ );
};
このコードをコンパイルしたいのですが:
Point<double,2> pt2d;
pt2d.Set( 25, 32 );
Point<double,3> pt3d;
pt3d.Set( 25, 32, 100 );
そしてこのコードは失敗します:
Point<double,2> pt2d;
pt2d.Set( 25, 32, 100 ); // Too many arguments
Point<double,3> pt3d;
pt3d.Set( 25, 32 ); // Too few arguments
これで、手動Point
で小さな次元に特化して無関係なSet
関数を作成できますが、基本的に同じコードを非C ++風に繰り返す習慣があります。さらに、intテンプレートパラメータのすべての可能な値に特化する必要はありません。
?の値ごとに特殊化コードを記述せずに、型の引数Point<Coord,dim>::Set()
を正確に受け取る関数を実装することは可能ですか?dim
Coord
dim
Boost.Hanaが使用するトリックを使用できますgetNth
:
template <typename Coord, int dim, typename = std::make_index_sequence<dim>>
struct Point;
template <typename Coord, int dim, size_t... Ignore>
struct Point<Coord, dim, std::index_sequence<Ignore...>>
{
void Set(decltype(Ignore, Coord{})... args)
{
// ...
}
};
Ignore
醜さを少し隠す(そしてデフォルトで構築Coord
できないものに対しては機能する)より長いバージョンは、メタプログラミングの定型文を追加することです:
template <typename... > struct typelist { };
template <int N, typename T, typename = std::make_index_sequence<N>>
struct repeat;
template <int N, typename T>
using repeat_t = typename repeat<N, T>::type;
template <int N, typename T, size_t... Idx>
struct repeat<N, T, std::index_sequence<Idx...>>
{
template <size_t >
struct makeT { using type = T; };
using type = typelist<typename makeT<Idx>::type...>;
};
そして、repeat_t
代わりに専門にします。そして、これを名前空間に隠して、ユーザーがそれを台無しにしないようにします。
namespace details {
template <typename Coord, int dim, typename = repeat_t<dim, Coord>>
struct Point;
template <typename Coord, int dim, typename... dimCoords>
struct Point<Coord, dim, typelist<dimCoords...>>
{
void Set(dimCoords... args)
{
}
};
}
template <typename Coord, int dim>
using Point = details::Point<Coord, dim>;
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加