6

C++ クラス内に次のコードがあります。

class Features
{
    #define Feature_Size_A 12345
    #define Feature_Size_B 45678
    #define Feature_Size_C 78901
    //#define Feature_Size_D 14725

    const int Feature_Sum = 0
    #ifdef Feature_Size_A
        + Feature_Size_A
    #endif
    #ifdef Feature_Size_B
        + Feature_Size_B
    #endif
    #ifdef Feature_Size_C
        + Feature_Size_C
    #endif
    #ifdef Feature_Size_D
        + Feature_Size_D
    #endif
        ;

    #ifdef Feature_Size_A
        static float Feature_A[Feature_Size_A];
    #endif
    #ifdef Feature_Size_B
        static float Feature_B[Feature_Size_B];
    #endif
    #ifdef Feature_Size_C
        static float Feature_C[Feature_Size_C];
    #endif
    #ifdef Feature_Size_D
        static float Feature_D[Feature_Size_D];
    #endif
};

さまざまなテストをコンパイルして実行するために、4 行目のような機能をコメントアウトしていました。しかし、クラスをテンプレートとして使用したいので、同じプログラムでさまざまな機能をオンまたはオフにした複数のバージョンをインスタンス化できます。

私はこのようなことを考えています:

template <bool Feature_A, bool Feature_B, bool Feature_C, bool Feature_D>
class Features
{
    ...
};

Features<true, true, true, false> f;

boost::mpl:vector を試してみましたが、ひどく苦労しています。

ところで: これは完全なコードではありません。元のコードには 25 個の機能があります。

マクロを含まないすべてのアイデアに感謝します:-)

4

3 に答える 3

3

タイプリストを使用して、この問題を解決できます。

template<unsigned num, unsigned size, typename T>
class Feature : public T
{
public:
    static float feature[size];
    static const unsigned int feature_sum = size + T::feature_sum;
};
template<unsigned num, unsigned size, typename T>
float Feature<num, size, T>::feature[size];
class Tail { 
public:
    static const unsigned feature_sum = 0; 
};

template<unsigned num, unsigned size, typename T>
float* get_feature_arr(Feature<num, size, T>& ref) 
{
    return ref.feature;
}

int main() {
    Feature<1, 12345, Feature<2, 45678, Feature<4, 78901, Tail>>> TripleFeatures;
    auto first = get_feature_arr<1>(TripleFeatures);
    auto third = get_feature_arr<4>(TripleFeatures);
    auto size = TripleFeatures.feature_sum;
}

これは、リストにある他の機能に関係なく、任意の機能にアクセスするためにも使用できます。

編集:配列を定義しない、識別子として「3features」を使用しようとするなど、詳細の一部をまとめました。Leが修正されました。コードはGCC4.7.1をコンパイルします。

于 2012-09-05T13:16:16.800 に答える
1

静的に割り当てられた配列を使用しないのはなぜですか?

#include <stdio.h>

template <bool Feature_A, bool Feature_B, bool Feature_C, bool Feature_D>
class Features
{
    static const int Feature_Size_A = 12345;
    static const int Feature_Size_B = 45678;
    static const int Feature_Size_C = 78901;
    static const int Feature_Size_D = 14725;
    static const int Feature_Sum = 0
        + Feature_A ? Feature_Size_A : 0
        + Feature_B ? Feature_Size_B : 0
        + Feature_C ? Feature_Size_C : 0
        + Feature_D ? Feature_Size_D : 0
    ;

public:
    static float Feature_Vector_A[Feature_A ? Feature_Size_A : 0];
    static float Feature_Vector_B[Feature_B ? Feature_Size_B : 0];
    static float Feature_Vector_C[Feature_C ? Feature_Size_C : 0];
    static float Feature_Vector_D[Feature_D ? Feature_Size_D : 0];
};

Features<true, true, true, true> f1;
Features<true, true, true, false> f2;

int main()
{
    printf("%d %d\n", sizeof(f1.Feature_Vector_D), sizeof(f2.Feature_Vector_D));
}

出力:

58900 0
于 2012-09-05T13:09:31.107 に答える
1

機能が正確に何であるかは明確ではありませんが、条件付きでメンバー関数とメンバーデータを含めることができるソリューションを次に示します。

namespace mpl = boost::mpl;

// Define your features
struct FeatureA
{
    static const int size = 12345;
    static float Feature_A[size];

    static void methodA() {}
};
float FeatureA::Feature_A[12345];

struct FeatureB
{
    static const int size = 45678;
    static char Feature_B[size]; // possibly different types of data (?)

    static void methodB() {}
};
float FeatureB::Feature_B[45678];

struct FeatureC
{
    static const int size = 78901;
    static int Feature_C[size];

    static void methodC() {}
};
float FeatureC::Feature_C[78901];


// Helper metafunction
template <typename T>
struct get_size 
  : mpl::int_<T::size>
{};


template <typename FeaturesSeq>
struct Features_impl 
  : mpl::inherit_linearly<
        FeaturesSeq,
        mpl::inherit<mpl::_, mpl::_>
    >::type
{
    static const int Feature_Sum = 
        mpl::accumulate<
            FeaturesSeq,
            mpl::int_<0>,
            mpl::plus<
                mpl::_1,
                get_size<mpl::_2>
            >
        >::type::value;
};

template <typename... F>
using Features = Features_impl<mpl::vector<F...>>;


#include <iostream>

int main()
{
    typedef Features<FeatureA, FeatureC> F;

    std::cout << F::Feature_Sum << '\n';

    F::Feature_A[0] = 12.0f;
    F::methodA();

    F::methodC();
}

あなたの例のように、すべての機能が本当に浮動小数点配列である場合は、ジェネリックFeatureクラスを使用できます

template <int Size>
struct Feature
{
    static float data[Size];
};
template <int Size>
float Feature::data[Size];

そして、このクラスの特殊化を mpl ベクトルに格納します。

typedef mpl::vector<Feature<1234>, Feature<5678>> Features;

mpl::at_c<Features, 0>::type::data[0] = 12.0f;
// could be encapsulated into a helper function

これらのいわゆる機能の目的に関する詳細情報がなければ、より完全な回答を提供することは困難です。

于 2012-09-05T14:15:53.283 に答える