首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >作为模板参数的泛型成员函数指针

作为模板参数的泛型成员函数指针
EN

Stack Overflow用户
提问于 2012-03-20 06:50:57
回答 2查看 32.3K关注 0票数 34

考虑下面的代码:

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

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

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

令人惊讶的是,g++没有抱怨Args不是模板列表中的最后一个参数,但无论如何它不能将proxycall绑定到正确的模板函数,只是注意到它是一个可能的候选。

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

编辑:正如一些人指出的那样,这个例子看起来毫无意义,因为proxycall不会传递任何参数。这在我正在处理的实际代码中并非如此:参数是通过一些模板技巧从Lua堆栈中获取的。但是这部分代码与问题无关,而且相当冗长,所以我不在这里粘贴它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-20 07:23:02

您可以尝试如下所示:

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

用法:

hello obj;

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

// or

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

Stack Overflow用户

发布于 2020-12-24 16:59:16

在现代C++中,可以使用template<auto>和通用的lambda-wrapper:

#include <utility>
#include <functional>

template<auto mf, typename T>
auto make_proxy(T && obj)
{
    return [&obj] (auto &&... args) { return (std::forward<T>(obj).*mf)(std::forward<decltype(args)>(args)...); };
}

struct R {};
struct A {};
struct B {};

struct Foo
{
    R f(A &&, const B &) { return {}; }
    //R f(A &&, const B &) const { return {}; }
};

int main()
{
    Foo foo;
    make_proxy<&Foo::f>(foo)(A{}, B{});
    //make_proxy<static_cast<R (Foo::*)(A &&, const B &) const>(&Foo::f)>(std::as_const(foo))(A{}, B{});
    //make_proxy<static_cast<R (Foo::*)(A &&, const B &)>(&Foo::f)>(foo)(A{}, B{});
}

如果有重载,应该像注释代码一样显式地指定成员函数类型。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9779105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档