重载模板类的更优雅的解决方案

时间:2012-11-05 20:36:49

标签: c++ class templates overloading

我有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行,请参阅here。 我发现这很难看,所以我正在寻找更优雅的解决方案。 有一个吗?

(顺便说一下,所有纠结的代码都是更复杂的事件系统的基础。)

2 个答案:

答案 0 :(得分:4)

你正在寻找C++11's variadic templates,正是出于这个目的而发明的。

或者,让单个模板参数T成为实际的函数类型,然后根据您的心愿,它可以是void()void(int)void(int, char)等。

顺便说一下,std::function<T>(或boost::function<T>)出了什么问题?这已经全部解决了。 : - )

答案 1 :(得分:1)

如果您的编译器不支持variadic templates,那么您可以尝试使用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);
    }
};

P.S。我同意“轨道中的轻度赛跑”,考虑使用boost / std :: function代替。