呼び出しをより簡潔にする方法でコンパイル時のゲッターを実装したいと考えています。から再帰的に継承する非型 ( unsigned int N
) クラス テンプレートがあります。Everyには と呼ばれる独自のメンバーがあり、対応する の値に初期化されます。ベースケースは. たとえば、オブジェクトにはと呼ばれる 6 つの があり、を通じて値が付けられます。コンパイル時の getter を実装したいのですが、プロトタイプの先頭に a を追加するほど簡単ではありません。foo
foo<N - 1>
foo
enum
number
N
foo<0>
foo<5>
enum
number
0
5
at
constexpr
template <unsigned int N>
struct foo : protected foo<N - 1> {
protected:
enum {number = N};
public:
constexpr int const& at(const unsigned int index) {
static_assert(index <= N, "out of range");
return this->foo<index>::number;
}
};
template <>
struct foo<0> {
protected:
enum {number = 0};
public:
constexpr int const& at(const unsigned int index) {
static_assert(index == 0, "out of range");
return this->number;
}
};
g++ 4.8 では、エラーのインスタンスがいくつか発生します: error: 'index' is not a constant expression
、とりわけ。残りはただ従うだけです。すべてのクライアント コードがat
整数リテラルのみで呼び出した場合でも、getter はコンパイルされません。なんで?
いずれにせよ、私の解決策は、コンパイル時の整数ラッパーを実装することでした。これは単純に非型 ( unsigned int N
) クラス テンプレートctint
(コンパイル時 int の略) であり、そのenum
メンバーmem
は次のように初期化されますN
。
template <unsigned int N>
struct ctint {
enum {mem = N};
};
したがって、foo<N>
およびfoo<0>
の getter メソッドをそれぞれ次のように置き換えます。
template <unsigned int ind>
constexpr int const& at(ctint<ind> const& ctint_par) {
static_assert(ctint_par.mem <= N, "out of range");
return this->foo<ctint_par.mem>::number;
}
と
template <unsigned int ind>
constexpr int const& at(ctint<ind> const& ctint_par) {
static_assert(ctint_par.mem == 0, "out of range");
return this->number;
}
作品:
int main() {
foo<5> f;
static_assert( f.at( ctint<4>{} ) != 4 , "equals 4");
}
しかし、関数呼び出しを冗長にします。<iostream>
何かが機能することを示すが、それを機能させるのに役立たない部分 (例: ) を除いて、ライブラリを使用しない実装が必要です。<>
ゲッターが、呼び出しで型名をオプションで省略したり、構文やスペルを省略したりできるようにしたいのですが、プロトタイプや定義では必須ではありません。sを巻き込みたくないarray[]
。それが無理なら次善の策を知りたいです。