1

次のように、3つのクラスがあります。

template <typename RET, typename ARG1 = int, [...], typename ARG5 = int>
class FunctionPointer {
    virtual operator()(ARG1, [...], ARG5);
};

template <typename RET, class TYPE, typename ARG1 = int, [...], typename ARG5 = int>
class ClassFunctionPointer : public FunctionPointer<RET, ARG1, [...], ARG5> {
    // make it so that class functions fit here
};

template <typename RET, typename ARG1 = int, [...], typename ARG5 = int>
class GlobalFunctionPointer : public FunctionPointer<RET, ARG1, [...], ARG5> {
    // make it so that non-member functions fit here
};

これらはすべてオーバーロードされているため、すべてのクラスは可変数の引数でインスタンス化できます。つまり、次の例はすべて有効です。

GlobalFunctionPointer<void> a(&test1);
GlobalFunctionPointer<void, int> b(&test2);
ClassFunctionPointer<void, TestClass, int, char> c(testObject, &TestClass::test1);
ClassFunctionPointer<void, TestClass, int, char, std::string, float, SomeClass> d(testObject, &TestClass::test2);

しかし、これらすべてのために、約 500 行の大量のコードを作成しました。ここを参照してください。これはかなり醜いので、よりエレガントなソリューションを探しています。まったくありますか?

(ちなみに、複雑なコードはすべて、より洗練されたイベント システムのベースになることを意図しています。)

4

2 に答える 2

4

あなたはまさにこの目的のために発明されたC++11 の variadic templatesを探しています。

または、単一のテンプレート引数Tを実際の関数型にすると、必要に応じてvoid()void(int)またはvoid(int, char)その他にすることができます。

ところで、std::function<T>(またはboost::function<T>)のどこが悪いの? これはすべてすでに解決されています。:-)

于 2012-11-05T20:38:17.723 に答える
1

コンパイラが可変個引数テンプレートをサポートしていない場合は、Boost.Preprocessorライブラリを使用してエミュレーションを試みることができます。

boost :: container :: vector :: emplace_backがどのように実装されているかを確認してください: http ://www.boost.org/doc/libs/1_51_0/boost/container/vector.hpp

Boost.Preprocessorを使用して、さまざまな数の引数を取る関数を自動生成します。事前定義された数の関数を生成します。

その結果、各関数を手作業で作成する必要がなくなります。代わりに、パターンを1回だけ書き込むことができます。

例えば:

#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>

struct Entity
{
#define ENTITY_PP_PARAM_LIST(z, n, data) const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n)
#define ENTITY_PP_PARAM_PASS(z, n, data) BOOST_PP_CAT(p, n)

#define BOOST_PP_LOCAL_MACRO(n) \
    template<typename GenericType BOOST_PP_ENUM_TRAILING_PARAMS(n, typename P) > \
    void AddComponent(BOOST_PP_ENUM(n, ENTITY_PP_PARAM_LIST, _)) \
    { \
        something=new GenericType(BOOST_PP_ENUM(n, ENTITY_PP_PARAM_PASS, _)); \
    } \
    /**/

#define BOOST_PP_LOCAL_LIMITS (0, 3)
#include BOOST_PP_LOCAL_ITERATE()
};

前処理後は次のように拡張されます。

struct Entity
{
    template<typename GenericType  >
    void AddComponent()
    {
        something=new GenericType();
    }

    template<typename GenericType , typename P0 >
    void AddComponent( const P0 & p0)
    {
        something=new GenericType( p0);
    }

    template<typename GenericType , typename P0 , typename P1 >
    void AddComponent( const P0 & p0 , const P1 & p1)
    {
        something=new GenericType( p0 , p1);
    }

    template<typename GenericType , typename P0 , typename P1 , typename P2 >
    void AddComponent( const P0 & p0 , const P1 & p1 , const P2 & p2)
    {
        something=new GenericType( p0 , p1 , p2);
    }
};

PS「軌道上の明度レース」に同意します。代わりにboost/std::functionを使用することを検討してください。

于 2012-11-05T20:46:38.407 に答える