1

首先,我不确定如何命名这个问题,所以我希望它足够好。

本质上,我有一大堆函数,它们具有仅因类型而异的通用功能。听起来像模板是吗?但这里有一个问题:每个函数都足够具体,以至于我想以不同的方式命名每个函数。

例如,看下面的代码:

bool GetFriendsList(FriendsListRequestData::CallbackType Callback)
{
    check(Callback != nullptr);
    FriendsListRequest* Request = new FriendsListRequest(this, GetNewRequestID());
    FriendsListRequestData* Data = new FriendsListRequestData(Request, Callback);
    return StoreAndPerformRequest(Data);
}

bool GetAccountInfo(AccountInfoRequestData::CallbackType Callback)
{
    check(Callback != nullptr);
    AccountInfoRequest* Request = new AccountInfoRequest(this, GetNewRequestID());
    AccountInfoRequestData* Data = new AccountInfoRequestData(Request, Callback);
    return StoreAndPerformRequest(Data);
}

// Many more routines...

这两个功能几乎相同。它们仅在类型和函数名称上有所不同。我可以将函数模板化,但它们将具有相同的名称。我用宏实现了以下内容,但我不喜欢它会使我的代码变得多么不可读:

#define IMPLEMENT_REQUEST_FUNCTION(Name, RequestType, RequestDataType)      \
bool Name(RequestDataType::CallbackType Callback)                           \
{                                                                           \
    check(Callback != nullptr);                                             \
    RequestType* Request = new RequestType(this, GetNewRequestID());        \
    RequestDataType* Data = new RequestDataType(Request, Callback);         \
    return StoreAndPerformRequest(Data);                                    \
}

class Foo
{
public:
    // other stuff...
    IMPLEMENT_REQUEST_FUNCTION(GetFriendsList, FriendsListRequest, FriendsListRequestData)
    IMPLEMENT_REQUEST_FUNCTION(GetAccountInfo, AccountInfoRequest, AccountInfoRequestData)
    // other stuff...
};

与在类和源代码中一遍又一遍地添加函数相比,我更喜欢宏,但是有没有办法在以不同方式命名结果函数的同时获得模板化功能,这样我就不必使用宏(或者可能使用更友好的宏)?

谢谢你。


编辑:我可能已经输入了太多的背景信息,并且歪曲了我实际询问的内容。本质上,我想知道是否可以在没有宏的情况下以某种方式获得上述宏的功能。我试图使函数名称保持不同,即使它们都具有基本相同的实现。

4

3 回答 3

1

关于什么:

template <typename R, typename D>
bool Get(typename D::CallbackType Callback)
{
    check(Callback != nullptr);
    R* Request = new R(this, GetNewRequestID());
    D* Data = new D(Request, Callback);
    return StoreAndPerformRequest(Data);
}

inline bool GetFriendsList(FriendsListRequestData::CallbackType Callback)
{
    return Get<FriendsListRequest, FriendsListRequestData>(Callback);
}

inline bool GetAccountInfo(AccountInfoRequestData::CallbackType Callback)
{
    return Get<AccountInfoRequest, AccountInfoRequestData>(Callback);
}

请注意,您可能还需要模板化StoreAndPerformRequest()

于 2013-08-09T21:17:29.547 回答
0

我不知道您的类型等,但这会起作用吗?

template<typename Req, typename Data>
bool getGeneric(Data::CallbackType Callback){
    if (Callback != nullptr) return false;
    Req* request = new T(this, GetNewRequestID()); //what is *this?
    Data* data = new Data(request,Callback);
    return StoreAndPerformRequest(data);
}

//getGeneric<FriendsListRequest, FriendsListRequestData> == GetFriendsList
//getGeneric<AccountInfoRequest, AccountInfoRequestData> == GetAccountInfo

顺便说一下,模板输入应该可以自动推导出来;我认为您不必明确声明它们,但是在某些情况下我以前对此是错误的。

于 2013-08-09T21:17:04.357 回答
0

可能最简单的方法是data为每个类添加一个(或类似的)typedef:

class FriendsListRequestData {};
class FriendsListRequest {
public:
    typedef FriendsListRequestData data;
    FriendsListRequest(some_class *s, int);
};

class AccountInfoRequestData{};
class AccountInfoRequest {
public:
    typedef AccountInfoRequestData data;
    AccountInfoRequest(some_class *s, int);
};

然后你可以编写如下调用代码:

class Foo {

template <class T>
bool Get(typename T::CallbackType t) {
    T *Request = new T(this, GetNewRequestID());
    typename T::data *Data = new typename T::data(Request, t);
    return StoreAndPerformRequest(Data);
}

...你会称之为:

auto bar = Get(some_callback);
auto baz = Get(another_callback);

如果您无法修改这些类,则必须将 typedef 移出到特征类型,并从那里使用它们:

template <class T>
struct req_traits {};

template<>
struct req_traits<FriendsListRequestData> {
    typedef FriendsListRequest req;
    typedef FriendsListRequestData data;
};

template<>
struct req_traits<AccountInfoRequestData> {
    typedef AccountInfoRequest req;
    typedef AccountInfoRequestData data;
};

template <class T, class traits=req_traits<T> >
bool Get(typename T::CallbackType t) {
    typedef typename traits::req req;
    typedef typename traits::data data;
    req *Request = new req(this, GetNewRequestID());
    data *Data = new data(Request, t);
    return StoreAndPerformRequest(Data);
}
于 2013-08-09T21:21:03.143 回答