0

呼び出しをより簡潔にする方法でコンパイル時のゲッターを実装したいと考えています。から再帰的に継承する非型 ( unsigned int N) クラス テンプレートがあります。Everyには と呼ばれる独自のメンバーがあり、対応する の値に初期化されます。ベースケースは. たとえば、オブジェクトにはと呼ばれる 6 つの があり、を通じて値が付けられます。コンパイル時の getter を実装したいのですが、プロトタイプの先頭に a を追加するほど簡単ではありません。foofoo<N - 1>fooenumnumberNfoo<0>foo<5>enumnumber05atconstexpr

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[]。それが無理なら次善の策を知りたいです。

4

0 に答える 0