簡體   English   中英

如何將非靜態成員函數傳遞給模板參數?

[英]how to pass non-static member function to template argument?

對於帶有函數模板參數的類模板,我希望以我類的一個函數作為其模板參數,使其成為我類的成員,或者使用 lambda 調用成員函數。 這是我想做的粗略示例,但我無法使其正常工作。

#include <iostream>

template<std::string (*fun)()>
struct wrapper{
    void operator()() {std::cout<<"wrapped "<<fun()<<std::endl;}
};

std::string foo() {
    return "foo";
}

struct bar{
    // static function works:
    static std::string str1() { return "bar1";}
    wrapper<str1> wrapped_bar1;

    // Non-static member function does not work:
    // std::string str2() { return "bar2";}
    // wrapper<&bar::str2> wrapped_bar2;

    // Lambda with *this does not work either:
    // static std::string str3(std::string input) { return input + "bar3";}
    // wrapper<[this](){return this->str3("bar")}> wrapped_bar3;
};

int main() {
    wrapper<foo> wrapped;
    wrapped();

    bar some_bar;
    some_bar.wrapped_bar1();
}

&bar::str2的類型是std::string (bar::*)()而不是std::string (*)() 有一些方法可以達到預期的效果,如下所示。 在下面顯示的示例中,我使wrapper成為普通的類類型而不是類模板。 此外,重載的opeartor()是模板化的,並且本身是用非模板化版本重載的。

struct wrapper{ //wrapper is not a class template anymore 
    
    void operator()(std::string (*fun)()) {std::cout<<"wrapped "<<fun()<<std::endl;}
    template<typename T> 
    void operator()(std::string (T::*fun)(), T obj) 
    {
        
        std::cout<<"wrapped "<<(obj.*fun)()<<std::endl;
        
    }
};

std::string foo() {
    return "foo";
}

struct bar{
    // static function works:
    static std::string str1() { return "bar1";}
    wrapper wrapped_bar1;

    
    std::string str2() { return "bar2";}
    
};

int main() {
    wrapper wrapped;
    wrapped(foo);

    bar some_bar;
    some_bar.wrapped_bar1(&bar::str1);
//------------------------------------vvvvvvvv---->pass the object also on which non-static member function should be called    
    some_bar.wrapped_bar1(&bar::str2, some_bar);
}

工作演示

上述修改程序的輸出為:

wrapped foo
wrapped bar1
wrapped bar2

沒有辦法制作wrapper<&bar::str2> wrapped_bar2;形式的東西。 按原樣工作。

考慮:

struct bar {
    std::string str2() { return "bar2";}
    wrapper<&bar::str2> wrapped_bar2;
};

bar b1;
bar b2;

現在b1.wrapped_bar2需要存儲指針&b1 ,並且b2.wrapped_bar2需要存儲指針&b2 這個( this )指針是調用實例(非靜態)方法所需的實例。

它顯然不能是靜態類型的一部分(如自由函數指針或成員函數指針本身),因為b1b2具有相同的類型但地址不同。 這意味着您至少需要編寫一個類似於

bar::bar() : wrapped_bar2{this} {}

現在,如果我們不得不這樣做,這兩個wrapper實例不能互換使用,我們不妨為成員函數編寫一個專用的包裝器類型:

template<typename Class, std::string (Class::*fun)()>
struct mem_wrapper{
    Class *instance_;

    explicit mem_wrapper(Class *that) : instance_(that) {}
    void operator()() {std::cout<<"wrapped "<< (instance_->*fun)() <<std::endl;}
};

如果你想要一個可以同時處理自由函數和成員函數的頂級類型,你需要一些方法來隱藏這些實現差異(類型擦除)。 老實說, std::function已經為您完成了所有這些工作,而且重新發明它有很多好處並不明顯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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