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 的可变参数模板。

或者,让单个模板参数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 自动生成采用不同数量参数的函数。它生成一些预定义数量的函数。

因此,您不必手动编写每个函数。相反,您只能编写一次您的模式。

例如:

#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 回答