2011-11-08 13 views
1

私は何かに道を究明しようとしている私の頭をラッキングしてきました。私はここに投稿して、誰かがアイディアを持っているかどうかを知ることができると思った。次のことを考えてみましょう:クラスへのポインタをとるテンプレート関数が必要ですが、クラス型やメンバー型を渡す必要はありません

template <typename S, typename T, T S::* pMember> 
bool SortByMember(const S& L, const S& R) 
{ 
    return L.*pMember < R.*pMember; 
} 

... 

struct SomeStruct 
{ 
    int SomeMember; 
}; 

void SomeFunction(void) 
{ 
    GetSortByMember<&SomeStruct::SomeMember>(); 
} 

私はSortByMemberの対応するインスタンス化に関数ポインタを返すために、機能、GetSortByMemberをしたいと思います。しかし、私は、ユーザーがクラス型とメンバ型を渡す必要がないように、GetSortByMemberを宣言/定義する方法について考えることはできません。これは:

GetSortByMember<SomeStruct, int, &SomeStruct::SomeMember>(); 

が過度に冗長であり、メンバータイプを記載する必要があります。私はおそらくブーストライブラリの解決策があると確信していますが、私はむしろ私が取り組んでいるプロジェクトにその依存関係を導入したくないです。

私はpsudocodeで使用した正確な構文が得られるとは思っていませんが、おそらくテンプレートクラスやマクロで何かできますか?

SortByMemberのシグネチャは、関数ポインタを使用するクラスによって予期されるため、変更することはできません。

+0

マクロを使用すると、エンデバー全体が非常に単純なように見えますか? –

+0

"member _function_へのポインタ"のような "メンバーへのポインタ"のようなものはありません。 –

+2

^これは間違っています。http://stackoverflow.com/questions/670734/c-pointer-to-class-data-memberを参照してください。 –

答えて

0

あなたが欲しいものを行うためのよりよい方法があるかもしれませんが、これはマクロとGCC特定typeof演算()を使用して動作します。私は確信していませんが、新しいC++標準でtypeofを実行する移植可能な方法があるかもしれません。

#include <iostream> 

template <class P, P p> 
class sort_by_member_t; 

template <class S, class T, T S::*p> 
class sort_by_member_t<T S::*, p> { 
public: 
    typedef bool (*fn_t)(S const&, S const&); 

    static bool fn(S const& L, S const& R) 
    { 
     return L.*p < R.*p; 
    } 
}; 

#define SORT_BY_MEMBER(p) sort_by_member_t<typeof(p), p>::fn; 

struct SomeStruct 
{ 
    int SomeMember; 
}; 


int main() 
{ 
    bool (*fp)(SomeStruct const&, SomeStruct const&); 
    fp = SORT_BY_MEMBER(&SomeStruct::SomeMember); 
    SomeStruct const a = { 1 }; 
    SomeStruct const b = { 2 }; 
    std::cerr 
     << (void*) fp << ' ' 
     << (*fp)(a, b) << ' ' 
     << (*fp)(b, a) << ' ' 
     << '\n'; 

    return 0; 
} 
+0

これはおそらく、私が何か良いものを見つけられないなら、私が使用するソリューションのラインに沿っているでしょう。コードを移植するのが好きですが、GCCを使用していますので、これはうまくいくでしょう。私は実際に新しいC++標準を使用する立場にはいませんが、本質的にはtypeofの標準化されたバージョンであるdecltypeキーワードを提供します。 –

+0

私はこれと似たようなことをしなければならないので、より良いアプローチを見たいと思っています。私は避けられない問題は、型を知っているときにのみ値をテンプレートに渡すことができるということです。以前の型パラメータから型を取得できますが、2つのパラメータを渡す必要があります。typeof/decltypeを使用して式の型を取得できますが、式を一度しか記述できない唯一の方法はマクロを使用することです。私は個人的にマクロが最終的な武器でなければならないということだけを普遍的に悪とみなさない。 –

0

あなたの例は明確ではありません。おそらく、結果の関数を2つの引数で呼び出す必要がありますか?もしそうなら、getter関数を使用して、例えば、それを渡すない理由:

#include <iostream> 

struct foo 
{ 
    int bar; 
    int getBar() const { return bar; } 
}; 

template <typename S, typename U> 
bool SortByMember(const S& L, const S& R, U f) 
{ 
    return (L.*f)()< (R.*f)(); 
} 

int main(void) 
{ 
    foo a = {1}; 
    foo b = {2}; 

    std::cout << SortByMember(a, b, &foo::getBar) << std::endl; 
} 
+0

2つの理由。 1つは、他のライブラリのクラスで作業している可能性があります。つまり、getBar関数を追加できません。 2つ目は、これは実行時の解決策ですが、私はコンパイル時の解決策を探しています。 また、実際には関数ポインタが必要です。なぜなら、そのポインタを格納してから後で呼び出すためです。 –

+0

これは無関係です。これは、元々データ型を参照していたメンバーへのポインタをメンバ関数へのポインタに変換します。 –

+0

@ TheOrangeMan:*コンパイル*と*ランタイム*ソリューションが意味することをさらに説明し、なぜ前者が必要なのかを説明できますか? –