簡體   English   中英

變量模板作為std :: function的參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM