2

質問に答えながら、メンバー関数のシグネチャの型定義にテンプレート エイリアスを利用することを提案しました。つまり、メンバー関数を型定義するだけでなく、メソッドを含むターゲット クラスを除外できます。

template<typename T>
using memberf_pointer = int (T::*)(int, int); 

これは質問が尋ねたことをカバーしているように見えますが、任意の関数引数に対して一般化しようとしました:

template<typename T, typename... Args>
using memberf_pointer = int (T::*)(Args&&...); 

引数推定の問題で失敗します (基本的に、空の引数リストを想定しています)。ここにデモがあります:

#include <iostream>

class foo
{
public:
  int g (int x, int y) { return x + y ; }
};

template<typename T, typename...Args>
using memberf_pointer = int (T::*)(Args&&...); 

int main()
{
  foo f ;
  memberf_pointer<foo> mp = &foo::g ;
  std::cout << (f.*mp) (5, 8) << std::endl ;
}

どうしてこれなの?それを機能させる方法はありますか?

4

4 に答える 4

1

質問のタイトルと本文の両方の文言は非常に誤解を招くものです。あなたの例では、どこでもゼロのテンプレート控除が行われています。あなたが書くとき:

memberf_pointer<foo> mp = &foo::g;

memberf_pointer<foo>はい、エイリアステンプレートですが、それはエイリアステンプレートの特定のインスタンス化です. の正確なタイプを提供しているため、控除は行われませんmp。その行は、次とまったく同じです。

int (foo:*mp)() = &foo::g;

g引数をとる明らかな理由でコンパイルされません。割り当てステートメントでテンプレート演繹を取得する方法は、次を使用することautoです。

auto mp = &foo::g;

の型は、呼び出しmpたのと同じ型になりUます。

template <typename U> void meow(U );
meow(&foo::g);

つまり、int (foo::*)(int, int).

同様に、次のことができます。

decltype(&foo::g) mp = &foo::g;

これにより、以前と同じタイプが得られます。

もちろん、正しい引数リストを指定したとしても:

memberf_pointer<foo, int, int> mp = &foo::g;

エイリアスが両方の引数に右辺値参照を追加するため、それでもコンパイルされません。mpthere isのタイプはint (foo::*)(int&&, int&&)一致しません&foo::g。おそらく、これを forwarding-reference によるかのように推論することを意図していたかもしれませんが、ここではそうではありません。エイリアスを正しく使用するには、次のように書き直す必要があります。

template<typename T, typename...Args>
using memberf_pointer = int (T::*)(Args...); 

memberf_pointer<foo, int, int> mp = &foo::g;

右辺値参照を取るメンバー関数があれば、それを明示的に提供できます。

class bar
{
public:
  int h(int&& x, int&& y) { return x + y ; }
};

memberf_pointer<bar, int&&, int&&> mb = &bar::h;
于 2015-07-27T14:14:52.027 に答える
1

C++ にはHindley-Milner型推論システムのような機能がなく、特定の右辺値の割り当てでは機能しません。

memberf_pointer<foo> mp = &foo::g ;

いくつかの簡単な回避策については、

  1. 構造体全体をドロップして使用するだけですauto

    auto mp = &foo::g;
    
  2. 型またはポインター型を明示的に提供する

    template<typename T>
    using memberf_pointer = T;
    
    memberf_pointer<decltype(&foo::g)> mp = &foo::g;
    

Cfr. テンプレート引数控除

于 2015-07-27T10:52:43.487 に答える