我的类中有一个成员函数_wrapper
,它封装了一些围绕其他函数族的常见逻辑。此包装函数接受指向正在包装的函数及其参数的指针。
我的类中的包装器实现类似于此示例类Foo
中的方式:
#include <functional>
class Foo
{
public:
void bar1(int a)
{
/// No-op.
}
void bar1(int a, int b)
{
/// No-op.
}
void bar2(const int & a)
{
/// No-op.
}
void foo(int x)
{
_wrapper_bar1(x); /// No problems to deduce type
_wrapper_bar2(x); /// No problems to deduce type
_wrapper(&Foo::bar1, x); /// Deduction fails
_wrapper(&Foo::bar2, x); /// Deduction fails
}
private:
template <typename ...Args>
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
{
/// Do some common stuff here...
(this->*method)(std::forward<Args>(args)...);
}
template <typename ...Args>
void _wrapper_bar1(Args && ...args)
{
bar1(std::forward<Args>(args)...);
}
template <typename ...Args>
void _wrapper_bar2(Args && ...args)
{
bar2(std::forward<Args>(args)...);
}
};
int main(int argc, char ** argv)
{
Foo().foo(123);
return 0;
}
当我将lvalue
,foo
的参数int x
传递给包装器时,clang
编译器抱怨冲突和演绎失败:
test.cpp:21:9: error: no matching member function for call to '_wrapper'
_wrapper(&Foo::bar1, x); /// Deduction fails
^~~~~~~~
test.cpp:27:10: note: candidate template ignored: deduced conflicting types for parameter 'Args' (<int> vs. <int &>)
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
^
test.cpp:22:9: error: no matching member function for call to '_wrapper'
_wrapper(&Foo::bar2, x); /// Deduction fails
^~~~~~~~
test.cpp:27:10: note: candidate template ignored: deduced conflicting types for parameter 'Args' (<const int &> vs. <int &>)
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
事情是我不明白为什么会这样。可以单独传递lvalue
,因为它是使用_wrapper_bar1
和_wrapper_bar2
完成的。这样做不会引起任何此类冲突,即const T &
vs T &
。
我知道解决此错误的方法:使用lvalue
将rvalue
投射到std::move(x)
,但显然不是修复,因为实际上并不需要移动。此外,有时我需要在调用包装函数后使用x
,并且使用移动的值是UB。
可能我的模板非常破碎,我遗漏了一些明显的东西。我很感激你的帮助。
修改重载Foo::bar1()
答案 0 :(得分:5)
在
template <typename ...Args>
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
Args
可以从2个地方推断出来。
您可以通过引入其他模板参数来解决这个问题:
template <typename ...Args, typename ...Arg2s>
void _wrapper(void (Foo::*method) (Args ...), Arg2s&& ...args)
{
/// Do some common stuff here...
(this->*method)(std::forward<Arg2s>(args)...);
}