通用成员函数指针作为模板参数 [英] generic member function pointer as a template parameter

查看:172
本文介绍了通用成员函数指针作为模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

  #include< iostream> 
使用命名空间std;

class hello {
public:
void f(){
cout<< f<" endl;
}
虚拟void ff(){
cout<< ff< endl;
}
};

#define call_mem_fn(object,ptr)((object)。*(ptr))

template< R(C :: * ptr_to_mem)(Args ...) > void proxycall(C& obj){
cout<< hello<< endl;
call_mem_fn(obj,ptr_to_mem)();
}

int main(){
你好obj;
proxycall<& hello :: f>(obj);
}

当然这不会在第16行编译,因为编译器不会不知道什么是 R C Args 。但是还有另一个问题:如果有人试图在 ptr_to_mem 之前定义那些模板参数,他就会遇到这种糟糕的情况:

  template< typename R,typename C,typename ... Args,R(C :: * ptr_to_mem)(Args ...)> 
// ^可变模板,但不作为最后一个参数!
void proxycall(C& obj){
cout<< hello<< endl;
call_mem_fn(obj,ptr_to_mem)();
}

int main(){
你好obj;
proxycall< void,hello和& hello :: f>(obj);
}

令人惊讶的是,g ++并不抱怨 Args 不是模板列表中的最后一个参数,但是无论如何它不能将 proxycall 绑定到正确的模板函数,而只是指出它是可能的候选者。 / p>

任何解决方案?我的最后一招是将成员函数指针作为参数传递,但如果我可以将其作为模板参数传递,则它将更适合我的其余代码。



编辑:
,正如有些人指出的,该示例似乎毫无意义,因为proxycall不会传递任何参数。在我正在使用的实际代码中,情况并非如此:参数是通过Lua堆栈中的一些模板技巧来获取的。但是那部分代码与问题无关,而且很冗长,因此我不会将其粘贴在这里。

解决方案

您可以尝试这样的操作:

  template< typename T,typename R,typename ... Args> 
R proxycall(T& obj,R(T :: * mf)(Args ...),Args&& ... args)
{
return(obj。 * mf)(std :: forward< Args>(args)...);
}

用法: proxycall(obj,& hello: :f);



或者,要使PTMF成为模板参数,请尝试专门化:

  template< typename T,T>结构代理

模板< typename T,typename R,typename ... Args,R(T :: * mf)(Args ...)>
struct proxy< R(T :: *)(Args ...),mf>
{
静态R调用(T& obj,Args& ... args)
{
return(obj。* mf)(std :: forward< Args>(args)...);
}
};

用法:

  hello obj; 

proxy< void(hello :: *)(),& hello :: f> :: call(obj);

//或

typedef proxy< void(hello :: *)(),& hello :: f> hello_proxy;
hello_proxy :: call(obj);


Consider this code:

#include <iostream>
using namespace std;

class hello{
public:
    void f(){
        cout<<"f"<<endl;
    }
    virtual void ff(){
        cout<<"ff"<<endl;
    }
};

#define call_mem_fn(object, ptr)  ((object).*(ptr))

template<R (C::*ptr_to_mem)(Args...)> void proxycall(C& obj){
    cout<<"hello"<<endl;
    call_mem_fn(obj, ptr_to_mem)();
}

int main(){
    hello obj;
    proxycall<&hello::f>(obj);
}

Of course this won't compile at line 16, because the compiler doesn't know what R, C and Args, are. But there's another problem: if one tries to define those template parameters right before ptr_to_mem, he runs into this bad situation:

template<typename R, typename C, typename... Args, R (C::*ptr_to_mem)(Args...)> 
                             //  ^variadic template, but not as last parameter!
void proxycall(C& obj){
    cout<<"hello"<<endl;
    call_mem_fn(obj, ptr_to_mem)();
}

int main(){
    hello obj;
    proxycall<void, hello, &hello::f>(obj);
}

Surprisingly, g++ does not complain about Args not being the last parameter in the template list, but anyway it cannot bind proxycall to the right template function, and just notes that it's a possible candidate.

Any solution? My last resort is to pass the member function pointer as an argument, but if I could pass it as a template parameter it would fit better with the rest of my code.

EDIT: as some have pointed out, the example seems pointless because proxycall isn't going to pass any argument. This is not true in the actual code I'm working on: the arguments are fetched with some template tricks from a Lua stack. But that part of the code is irrelevant to the question, and rather lengthy, so I won't paste it here.

解决方案

You could try something like this:

template <typename T, typename R, typename ...Args>
R proxycall(T & obj, R (T::*mf)(Args...), Args &&... args)
{
    return (obj.*mf)(std::forward<Args>(args)...);
}

Usage: proxycall(obj, &hello::f);

Alternatively, to make the PTMF into a template argument, try specialization:

template <typename T, T> struct proxy;

template <typename T, typename R, typename ...Args, R (T::*mf)(Args...)>
struct proxy<R (T::*)(Args...), mf>
{
    static R call(T & obj, Args &&... args)
    {
        return (obj.*mf)(std::forward<Args>(args)...);
    }
};

Usage:

hello obj;

proxy<void(hello::*)(), &hello::f>::call(obj);

// or

typedef proxy<void(hello::*)(), &hello::f> hello_proxy;
hello_proxy::call(obj);

这篇关于通用成员函数指针作为模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆