Gre*_*ape 1 c++ templates c++11
我的类中有一个成员函数_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;
}
Run Code Online (Sandbox Code Playgroud)
当我传递一个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)
Run Code Online (Sandbox Code Playgroud)
事情是我不明白为什么会发生这种情况.可以lvalue单独传递,因为它是使用_wrapper_bar1和完成的_wrapper_bar2.而这样做不会上升这种,即任何冲突const T &VS T &.
我知道解决这个错误的方法:通过转换lvalue为rvalue使用std::move(x),但显然它不是修复,因为实际上并不需要移动.另外,有时我需要x在调用包装函数后使用,并且使用移动值是UB.
可能我的模板很破碎,我遗漏了一些明显的东西.我很感激你的帮助.
编辑:重载Foo::bar1()
在
template <typename ...Args>
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
Run Code Online (Sandbox Code Playgroud)
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)...);
}
Run Code Online (Sandbox Code Playgroud)