【问题标题】:Variadic Templates, std::function and lambdas as class members可变参数模板、std::function 和 lambdas 作为类成员
【发布时间】:2018-10-24 07:26:55
【问题描述】:

我在这里有几个类,第一个是存储std::function 类型的类。

template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
    std::function<RES_TYPE( ARG_TYPES... )> call_back;
};

我有另一个类,它将注册来自函数对象、函数指针或 lambda 的传入函数,并存储上述类的实例,并有另一个将调用它的成员函数。

template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
    Functor<RES_TYPE, ARG_TYPES...> callback_;

public:
    Driver() = default;
    ~Driver() = default;

    void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
        callback_ = func;
    }

    RES_TYPE call_back( ARG_TYPES... args ) {
        return callback_( args... );
    }    
};

当我试图调用它时,我正在努力将语法正确地传递给我试图传递函数值的位置。我的主要看起来像这样:

int main() {    
    Functor<int, int, int> func;
    auto lambda = []( int a, int b ) { return a + b; };
    func.call_back = lambda;

    Driver<int, int, int> driver;
    driver.register_callback( func );
    std::cout << driver.call_back( 3, 5 ) << '\n';

    return 0;
}

我似乎无法理解语法中缺少的内容。我已经尝试了其他各种方法,但是使用当前的设置,我从 Visual Studio 2017 CE 中得到了这个编译器错误:

1>------ Build started: Project: Temp, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\main.cpp(62): error C2064: term does not evaluate to a function taking 2 arguments
1>c:\...\main.cpp(62): note: while compiling class template member function 'RES_TYPE Driver<RES_TYPE,int,int>::call_back(int,int)'
1>        with
1>        [
1>            RES_TYPE=int
1>        ]
1>c:\...\main.cpp(77): note: see reference to function template instantiation 'RES_TYPE Driver<RES_TYPE,int,int>::call_back(int,int)' being compiled
1>        with
1>        [
1>            RES_TYPE=int
1>        ]
1>c:\...\main.cpp(75): note: see reference to class template instantiation 'Driver<int,int,int>' being compiled
1>Done building project "Temp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我知道编译器告诉我什么,但我似乎无法获得正确的语法来存储这个 lambda,然后才能调用它。我试图使这些类尽可能通用,以便它可以接受 lambda、函数对象或函数指针。


解决方案

我的代码现在看起来像这样并且工作正常!

template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
    std::function<RES_TYPE( ARG_TYPES... )> func_;
};

template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
    Functor<RES_TYPE, ARG_TYPES...> functor;

public:
    Driver() = default;
    ~Driver() = default;

    void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
        functor = func;
    }

    RES_TYPE call_back( ARG_TYPES... args ) {
        return functor.func_( args... );
    }    
};

int main() {    
    Functor<int, int, int> func;
    auto lambda = []( int a, int b ) { return a + b; };
    func.func_ = lambda;

    Driver<int, int, int> driver;
    driver.register_callback( func );
    int a = 3;
    int b = 5;
    std::cout << driver.call_back( a, b ) << '\n';
    std::cout << driver.call_back( 7, 5 ) << '\n';

    Functor<void, std::string, std::string> func2;
    auto lambda2 = []( std::string str1, std::string str2 ) {
        str1 = str1 + " " + str2;
        std::cout << str1 << '\n';
    };

    Driver <void, std::string, std::string> driver2;
    func2.func_ = lambda2;
    std::string str1 = "Hello";
    std::string str2 = "World";
    driver2.register_callback( func2 );
    driver2.call_back( str1, str2 );
    driver2.call_back( "Generic", "Programming" );

    return 0;
}

预期输出:

8
12
Hello World
Generic Programming

实际输出:

8
12
Hello World
Generic Programming

程序退出:

Code (0)

【问题讨论】:

    标签: templates lambda c++17 variadic-templates std-function


    【解决方案1】:

    您正尝试在名为 callback_Functor 实例上调用 operator()(int, int)。相反,您需要将此结构的数据成员命名为call_back。像这样:

    RES_TYPE call_back( ARG_TYPES... args ) {
        return callback_.call_back( args... );
    }
    

    【讨论】:

    • 非常感谢:我是新的,我很接近;并且遗漏了一些琐碎的事情,但有时有第二双眼睛总是很好!
    • 是的,我知道前向引用;但试图首先摆脱编译器错误!
    • 而一个名为callback_ 的数据成员有一个需要调用的名为call_back 的数据成员确实很容易出错:)
    • 是的,我同意;我将修复一些命名约定!只是试图让代码按预期工作!
    • 我忽略了 call_back 方法在非推导上下文中......这意味着 ARG_TYPE&amp;&amp;... 没有命名通用引用,而是命名右值引用,因为模板参数类型有已经在类构造时指定。我的错。我会调整答案!最好的办法是你也将你的问题缩减为原始版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 2014-01-03
    • 2022-01-05
    相关资源
    最近更新 更多