2

以下に示すテンプレートでは、(コンパイル呼び出しRun(&Base::foo)で行われるように) Base タイプに 2 回名前を付ける必要なく、呼び出しが成功することを望みます。Run<Base>(&Base::foo)それもらっていいですか?おそらく、大量のBoostヘッダーを追加せずに?

提供されたコードでは、次のエラーが発生します。

prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’

( http://ideone.com/8NZkqでスニペットをいじることができます):

#include <iostream>

class Base {
public:
  bool foo() { return true; }
};

Base* x;

template<typename T>
struct Traits {
  typedef bool (T::*BoolMethodPtr)();
};

template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
  T* y = dynamic_cast<T*>(x);
  std::cout << (y->*check)();
}

int main() {
  Base y;
  x = &y;
  Run<Base>(&Base::foo);
  Run(&Base::foo); // why error?
}
4

4 に答える 4

10

TinはTraits<T>::BoolMethodPtr推定されないコンテキストにあるため、コンパイラは呼び出しから T の型を自動的に推定しません。これは、次のようなコードが存在する可能性があるためです。

template<typename T>
struct Traits {
  typedef bool (T::*BoolMethodPtr)();
};

template<>
struct Traits<int> {
  typedef bool (Base::*BoolMethodPtr)();
};

Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */

Traits<T>クラスなしでできる場合は、次のように記述できますRun

template<class Class>
void Run(bool (Class::*check)()) {
  Class* y = dynamic_cast<Class*>(x);
  std::cout << (y->*check)();
}

このコンテキストでは、次のClassことを意味すると推測できますBase

于 2010-09-30T12:55:57.597 に答える
4

型、任意の型を分離するには、部分的な特殊化を使用します。関数テンプレートの部分的な特殊化はないため、引数の型で関数を直接パラメーター化し、内部のクラス型を取得する必要があります。

template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this

template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
     typedef C host;
     typedef void sfinae; // disallow function for non ptmf arguments
};

template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
    typedef T BoolMethodPtr; // or something
    typedef typename get_host_class< T >::host host;
}
于 2010-09-30T12:55:42.793 に答える
2

これは非推定コンテキストだと思います。

$14.8.2.5/5-「推定されないコンテキストは次のとおりです。 — 修飾 ID を使用して指定された型のネストされた名前指定子。」

この場合に当てはまる言葉だと思います。しかし、一部のテンプレートの神々は私の理解を承認する必要があります.

于 2010-09-30T12:43:10.273 に答える
2

コンパイラがテンプレート引数を照合しようとするとき、プライマリ クラス タイプのみが考慮されます。つまり、次の式に遭遇すると、次のようになります。

Run(&Base::foo);

...そして、のテンプレートパラメータを把握しようとしています。それ自体Runのタイプのみを考慮し、どのクラスがその一部であるかはfoo考慮しません。foo

編集:

の型はfooですがbool(Base::*)(void)、コンパイラに見つけてもらいたいのはBase

于 2010-09-30T12:44:01.973 に答える