如何从 C 中的方法类型推导类类型模板?

发布于 2024-09-25 05:41:46 字数 912 浏览 8 评论 0原文

在如下所示的模板中,我希望调用 Run(&Base::foo) 成功,而无需两次命名 Base 类型(如编译 Run中所做的那样) ;(&Base::foo) 调用)。我可以要那个吗?可能不需要添加大量 Boost 标头?

使用提供的代码,我收到错误:(

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

您可以在 http://ideone.com/8NZkq< /a>):

#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?
}

In templates as shown below, I would like the call Run(&Base::foo) succeed without the need to name the Base type twice (as is done in the compiling Run<Base>(&Base::foo) call). Can I have that? Possibly without adding a ton of Boost headers?

With the provided code, I get an error of:

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

(you can fiddle with the snippet at 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?
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

合久必婚 2024-10-02 05:41:46

Traits::BoolMethodPtr 中的 T 处于非推导上下文中,因此编译器不会从调用中自动推导 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 类,则可以将 Run 编写为:

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

在此上下文中,Class 可以推断为 Base 的意思

The T in Traits<T>::BoolMethodPtr is in a non-deduced context, so the compiler will not deduce automatically from the call what type T should be.
This is because there could be code like this:

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 */

If you can do without the Traits<T> class, you can write Run as:

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

In this context, Class can be deduced to mean Base

a√萤火虫的光℡ 2024-10-02 05:41:46

要区分一种类型(任何类型),请使用部分特化。没有函数模板部分专业化,因此您需要直接在其参数类型上参数化函数并检索内部的类类型。

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;
}

To pick apart a type, any type, use partial specialization. There is no function template partial specialization, so you'll need to directly parameterize the function on its argument type and retrieve the class type inside.

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;
}
蓝礼 2024-10-02 05:41:46

我认为这是一个非推导的上下文。

$14.8.2.5/5-“非推导的上下文
是: — a 的嵌套名称说明符
使用指定的类型
合格的 ID。”

我认为这句话适用于这种情况。但是一些模板大神需要批准我的理解。

I think this is a non deduced context.

$14.8.2.5/5- "The non-deduced contexts
are: — The nested-name-specifier of a
type that was specified using a
qualified-id."

I think this is the quote that applies in this case. But some template gods need to ratify my understanding.

属性 2024-10-02 05:41:46

当编译器尝试匹配模板参数时,它仅考虑主类类型。换句话说,当它遇到表达式:

Run(&Base::foo);

...并且它试图找出 Run 的模板参数时,它只考虑 foo 本身的类型,而不会不考虑 foo 所属的任何类。

编辑:

foo 的类型是 bool(Base::*)(void),但您希望编译器找到的只是 Base >

When the compiler tries to match a template argument, it only considers the primary class type. In other words, when it encounters the expression:

Run(&Base::foo);

...and it's trying to figure out the template parameter for Run, it only considers the type of foo itself, and doesn't consider whatever class foo is a part of.

EDIT:

And the type of foo is bool(Base::*)(void), but what you want the compiler to find is just Base

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文