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...

2 つの機能はほぼ同じです。型と関数名のみが異なります。関数をテンプレート化することはできますが、それらは同じ名前になります。マクロを使用して以下を実装しましたが、コードが読みにくくなるのが好きではありません。

#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 を traits 型に移動し、そこから使用する必要があります。

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 に答える