[英]Variadic template as parameters to std::function
我想構建一個允許我用未定義數量的參數調用成員函數的結構。 現在我寫了這樣的東西
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<Return<Args&& ...)> callerFunction
一個事實:我無法將std :: function變量聲明為std::function<Return<Args&& ...)> callerFunction
當我嘗試這樣做時,編譯器說它不能從int
轉換為int&&
(例如,如果參數是int
),所以我猜測該函數將Args&& ...
視為rvalue引用的參數包。 我對么?
有解決方法嗎?
編輯:好的,我以錯誤的方式在Caller構造函數中聲明了該函數。
錯誤的方式 - > Caller(Class& instance, Return(Class::*function)(Args&& ...))
正確的方法 - > 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&?的情況下聲明函數?
當您像這樣定義類模板時:
template <typename T>
struct A {
A(T&& param)
}
然后創建一個實例:
A<int> myInstance(someIntVariable);
它不會編譯 。 原因是, T
的類型由您明確指定(作為int
,在A<int>
),並且您的類構造函數參數不再是T&&
,而是int&&
,因此它不再是通用引用(它同時接受左值和右值參考),但是常規右值參考。
接下來,如果傳遞一些整數,則會出現類型不匹配錯誤,因為在期望rvalue引用時傳遞常規變量。
在您的示例中,您明確定義了函數簽名,因此同樣適用 - 構造函數需要一個函數將rvalue引用到Args ...,但事實並非如此。
我認為在這個問題中解釋得更好
int&&
與int
。 如果您的方法采用int
,則不需要int&&
。 它們是不同的類型。
成員函數指針的不同簽名之間沒有轉換。
轉發引用並不神奇。 它們依賴於演繹規則(並且不使用上面的Args&&...
在推導的上下文中)和參考折疊規則。
就這樣,你的
Return operator() (Args&& ... args)
也是錯的。 如果Args...
是int
,那么你將無法使用int a; blah.operator()(a)
調用上面int a; blah.operator()(a)
int a; blah.operator()(a)
作為a
不會綁定到int&&
。
老實說,你的整個類型應該被拋出並替換為std::function<Return(Args...)>
。 Class
是函數所做的無用的縮小,你的包裝器也不會增加太多。
用戶只需[&a](auto&&...args)->decltype(auto){ return a.foo(decltype(args)(args)...); }
[&a](auto&&...args)->decltype(auto){ return a.foo(decltype(args)(args)...); }
如果他們真的需要復制你的構造函數,或使用std::bind( &A::foo, std::ref(a) )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.