1

Listクラスのオブジェクトを並べ替えるために使用しているジェネリック関数があります。

この関数は非常にうまく機能しますが、そのクラスのメンバー関数への関数ポインターを使用してこの関数をクラスに適用したい場合、ビルドされません。

関数は次のとおりです。

template <typename T1, typename T2, typename T3>
void DialogFaitListing::trie(T1 * list, T2 (T1::*fx)(quint16), T3 (T2::*crit)())
{
    for(int i(0);i<list->count();i++)
    {
        for(int j(i);j<list->count();j++)
        {
            if((((list->*fx)(i)).*crit)() > (((list->*fx)(j)).*crit)())
            {
                list->swap(i,j);
            }
        }
    }
}

ここで、listはオブジェクトのリストを含むクラス、fxはオブジェクトにアクセスするための関数ポインター、critはソート用のオブジェクト比較関数です。

この行を使用してビルドする場合:

trie(vend,&Vendeurs::getVend,&Vendeur::getNom);

このエラーが発生します:

dialogfaitlisting.cpp:459: erreur : no matching function for call to 
'DialogFaitListing::trie(Vendeurs*&, Vendeur (Vendeurs::*)(quint16), 
QString (Personne::*)())'

ps:私の悪い英語でごめんなさい

4

2 に答える 2

0

&Vendeur::getNom、を介してアクセス可能なメンバーであるにもかかわらず、Vendeurタイプがであるように見えますQString (Personne::*)()。これはT2、テンプレート引数の推論中にあいまいになります:Vendeurそれですか、Personneそれともですか?

trieバンドエイドの修正は、呼び出し元に明示的に変換する負担をかけるQString (Vendeur::*)()ことであり、次の呼び出しになります。

trie(vend, &Vendeurs::getVend, static_cast<QString (Vendeur::*)()>(&Vendeur::getNom));

crit渡すエリオンが基本クラスから来るたびに同じエラーが見つかる可能性があることを考えると、これは非常に冗長で不便です。

より良い解決策は、が表示される2つのスポットのいずれかでテンプレート引数の推論を禁止することT2です。そのために2番目のスポットを選択するのは理にかなっていると思います。

template<typename T>
struct identity { typedef T type; };

template <typename T1, typename T2, typename T3>
void trie(T1 * list
     , T2 (T1::*fx)(quint16)
     , T3 (identity<T2>::type::*crit)());

次に、呼び出しでは、であるとT2推定することしかできず、暗黙的にに変換されます。Vendeur&Vendeur::getNomQString (Vendeur::*)()

于 2012-09-18T18:07:54.640 に答える
0

の2番目の引数(のため)と3番目の引数に同時に制約しようとしているようですT2(ただし、何らかの継承などがない限り、からへの移行方法はわかりません)。それよりも少し多くのコードを投稿する必要があるかもしれません(特にクラス定義)。VendeurtrieVendeur Vendeurs::getVend(quint16)Personne&Vendeur::getNomQstring Personne::function()

于 2012-09-18T17:44:41.160 に答える