我想构建一个允许我用未定义数量的参数调用成员函数的结构。现在我写了这样的东西
template<typename Class, typename Return, typename ... Args>
struct Caller
{
private:
std::function<Return(Args ...)> callerFunction;
Caller() = delete;
Caller(const Caller&) = delete;
Caller(Caller&&) = delete;
Caller& operator=(const Caller&) = delete;
public:
~Caller() = default;
Caller(Class& instance, Return(Class::*function)(Args ...))
{
callerFunction = [&instance, function](Args... args)
{
return (instance.*function)(args ...);
};
}
Return operator() (Args ... args)
{
return callerFunction(args ...);
}
};
我担心我不能解决这个事实,即我不能将std :: function变量声明为std::function<Return<Args&& ...)> callerFunction
当我尝试这样做时,编译器说它无法从int
转换为int&&
(例如参数是int
s),所以我猜测函数将Args&& ...
视为右值引用的参数包。我是对的吗?
有解决方法吗?
编辑:好的,我以错误的方式在Caller构造函数中声明了这个函数。
错误的方式 - &gt; Caller(Class& instance, Return(Class::*function)(Args&& ...))
正确的方式 - &gt; Caller(Class& instance, Return(Class::*function)(Args ...))
(我猜)正确的实现是
template<typename Class, typename Return, typename ... Args>
struct Caller
{
private:
std::function<Return(Args&& ...)> callerFunction;
Caller() = delete;
Caller(const Caller&) = delete;
Caller(Caller&&) = delete;
Caller& operator=(const Caller&) = delete;
public:
~Caller() = default;
Caller(Class& instance, Return(Class::*function)(Args ...))
{
callerFunction = [&instance, function] (Args&&... args)
{
return (instance.*function)(std::forward<Args>(args) ...);
};
}
Return operator() (Args&& ... args)
{
return callerFunction(std::forward<Args>(args) ...);
}
};
现在的问题是:为什么我需要在没有double&amp;的情况下声明该函数?
答案 0 :(得分:1)
当您像这样定义类模板时:
template <typename T>
struct A {
A(T&& param)
}
然后创建一个实例:
A<int> myInstance(someIntVariable);
它不会编译。原因是,T
的类型是由您明确指定的(int
中的A<int>
),而您的类构造函数参数不再是T&&
,而是{ {1}},因此它不再是通用引用(它接受左值和右值引用),而是常规的右值引用。
接下来,如果你传递一些整数,则会出现类型不匹配错误,因为在期望rvalue引用时传递常规变量。
在你的例子中你明确定义了函数签名,所以同样适用 - 构造函数需要一个函数对rgs引用rval引用...但是这不是真的。
我认为更好地解释了in this question
答案 1 :(得分:0)
int&&
与int
不同。如果您的方法采用int
,则不会使用int&&
。它们是不同的类型。
成员函数指针的不同签名之间没有转换。
转发引用并不神奇。它们依赖于演绎规则(并且在推导的上下文中不使用上面的Args&&...
)和参考折叠规则。
因此,你的
Return operator() (Args&& ... args)
也错了。如果Args...
为int
,则您无法通过int a; blah.operator()(a)
调用上述内容,因为a
无法绑定int&&
老实说,您的整个类型应该被抛弃并替换为std::function<Return(Args...)>
。 Class
对函数的作用是无用的缩小,而且你的包装也不会增加太多。
如果用户确实需要复制构造函数,或者使用[&a](auto&&...args)->decltype(auto){ return a.foo(decltype(args)(args)...); }
std::bind( &A::foo, std::ref(a) )