我在我的類中有一個成員函數_wrapper
,它封裝了一些其他函數族的一些公共邏輯。這個包裝函數接受指向正在被包裝的函數和它的參數的指針。候選模板被忽略:參數的推導衝突類型:<const T &> vs <T &>
包裝在我班上的實現方式類似於它是如何在這個例子中類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 &
與T &
。
我知道一個解決此錯誤的方法:使用std::move(x)
將lvalue
轉換爲rvalue
,但顯然它不是一個修復方法,因爲移動實際上不是必需的。此外,有時我需要在調用包裝函數後使用x
,並且使用移動的值是UB。
可能我的模板非常壞,我錯過了一些明顯的事情。我會很感激你的幫助。
編輯:重載Foo::bar1()
在'模板<類型名...參數數量>空隙_wrapper(無效(美孚:: *方法)(參數數量。 ..),Args && ... args)'注意第二個Args強制右值引用... – Jarod42 2015-03-31 11:30:22
@ Jarod42,好吧,它實際上是* universal reference *,它不強制右值。 – GreenScape 2015-03-31 11:33:01
我的意思是它在成員函數指針,並在正常參數。你可能想要'template void _wrapper(void(Foo :: * method)(Args ...),Arg2s && ... args)' –
Jarod42
2015-03-31 11:43:41