2

在如下所示的模板中,我希望调用Run(&Base::foo)成功而不需要两次命名 Base 类型(就像在编译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

编辑:

的类型foobool(Base::*)(void),但你希望编译器找到的只是Base

于 2010-09-30T12:44:01.973 回答