c++ - 获取与模板 arg 中传递的函数成员类型相同的类

标签 c++ templates function-pointers

我正在尝试,但我不知道当我将派生类的函数成员指针作为模板参数传递时如何(但可能不可能)捕获相同类型的类。

例如,有这段代码,

class CObject{

public:
    string m_id;

    void setID(const char * id){
        printf("assign id %s\n",id);
        m_id=string(id);
    }

     ~CObject(){}
};


class CDerivedObject:public CObject{
public:
    ~CDerivedObject(){};
};

有了这个函数模板,

template < typename _R, class _T, typename..._A>
void function_template_test(_R (_T:: *function_type)(_A...) )
{

    printf("ObjectTypeIs: %s\n",typeid( _T).name());
}

在主函数中,我调用 function_template_test 传递函数指针成员 CDerivedObject::setID,

function_template_test(&CDerivedObject::setID);

如果我用 g++ 编译此代码(我的最新版本是 5.4.0),它会打印 7CObject ,这意味着 _T 是 CObject 类型,但在参数中我传递了 CDerivedObject::setID。我知道函数setID函数属于CObject,所以编译器以这种方式获取类型,但是...

有没有可能的方法来捕获我传递给模板参数的类类型(即 _T 是 CDerivedObject)?

编辑 1

我的问题的解决方案可能是这样的,

template < class _C, class _R, typename _T, typename..._A>
void _function_template_test(_R (_T:: *function_type)(_A...) )
{

    printf("ObjectTypeIs: %s\n",typeid( _C).name());
}

#define function_template_test(cl, fun)\
        _function_template_test<cl>(&cl::fun)

然后我将该函数称为,

function_template_test(CDerivedObject,setID);

是一个解决方案,但我更喜欢模板而不是宏。

最佳答案

考虑这个程序:

struct Base { void foo() {} };
struct Derived: Base {};

auto main() -> int
{
    int x = &Derived::foo;
}

这是使用 MinGW g++ 编译的结果:

[H:\forums\so\056]
> g++ main.cpp
main.cpp: In function 'int main()':
main.cpp:6:23: error: cannot convert 'void (Base::*)()' to 'int' in initialization
     int x = &Derived::foo;
                       ^~~

[H:\forums\so\056]
> _

As you can see the type of &Derived::foo is void (Base::*)() (and yes, that's according to the standard).

I.e., when you ask

Is there a possible way to capture the class type I'm passing on template parameter

... that's what you're doing.

To make that type void (Derived::*)() you need a function declared in Derived.


For your case of calling a function that takes a member function pointer, you can alternatively specify all the template arguments explicitly. That works because a void (Base::*)() converts implicitly to void (Derived::*)(). And yes that's counter-intuitive, and constitutes a little loop-hole in the C++ type system, but it's the way the logic works out when you consider what kinds of objects a member function can be called on.


Re the loop-hole, here's an example (see ma, no casts!):

#include <iostream>
#include <stack>
using namespace std;

auto main()
    -> int
{
    stack<int> st;
    for( int const i : {1, 2, 3} ) { st.push( i ); }

    struct Hack: stack<int> { using stack<int>::c; };
    int const n = (st.*&Hack::c).size();
    cout << "That stack contains " << n << " items." << endl;
}

关于c++ - 获取与模板 arg 中传递的函数成员类型相同的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48601298/

相关文章:

c++ - SFINAE 启用非模板成员函数

c++ - 我应该在 c++ 类中使用什么,有或没有 "new"?

c++ - 模板类问题;正确的模板签名?

c - 优化辅助函数

c - 使用通用函数指针

c++ - valgrind 是否检测到 OpenGL 内存泄漏?

c++ - Qt FramelessWindowHint 和 WA_TranslucentBackground 字体渲染

c++ - 我想了解 C++ 中的参数解包

c++ - 为什么 C++11 不支持 'std::function<void(int, ...)>' ?

c - 从 "Address of a function"开始的字节中有什么?如何知道要考虑多少字节?