【问题标题】:c++ vector of function with template argumentsc++ 带有模板参数的函数向量
【发布时间】:2020-10-26 14:27:10
【问题描述】:
#include<iostream>
#include<functional>
#include <unordered_set>
#include <vector>
#include <unordered_map>
#include <variant>




class Button
{
public:
    Button(int _val):val(_val){}
    ~Button();
    int val;
    
    template<typename F, typename...InArgs>
    void addListener(std::function<F(InArgs...)>(f), InArgs... args) {
        listener.push_back(f(args...));
    }

    template<typename F, typename...InArgs>
    void callMethod(std::function<F(InArgs...)>(f), InArgs... args) {
        f(args...);
    }
    
    void print() { std::cout << "Button value -> " << val << std::endl; }
private:
    template<typename F,typename...InArgs>
    static std::vector<std::function<F(InArgs...)>> listener;
    
};

inline void test1() {
    std::cout << "Printing test1 method...\n";
}
inline void test2(Button* b) {
    std::cout << "Button value is 20.\n";
    b->val = 20;
}
inline void test3(Button* b, int a) {
    std::cout << "Button value is passed parameter.\n";
    b->val = a;
}
inline void test4(int a) {
    std::cout << "print " << a << std::endl;
}
class AppThree
{
public:
    static void run() {
        Button* button = new Button(5);
        button->print();
        //button->callMethod(std::function<void(int)>(&test4), 1); //work it
        button->addListener(std::function<void(int)>(&test4),1); // error
        

    }
};

我想要带有向量参数的推送函数。我想从向量中调用所有函数,但我无法添加函数。我收到 C3245 错误。我不知道哪里失败了。如果我的想法不正确,请展示真实的方式。 对不起我的英语不好:D

【问题讨论】:

  • 什么是 C3245 错误?你能提供完整的错误文本吗?
  • 假设使用VS,编译器错误C3245描述为:'function': use of a variable template requires template argument list
  • @JMCampos 完全正确..
  • @HasanOz 最好发布完整的错误文本,因为它通常会给出它发生的行。
  • 您有一个成员变量模板listener,这意味着您对于每个函数类型都有一个向量。编译器无法推断出你的意思。您还试图 push_back 调用函数的结果,而不是函数本身。

标签: c++ templates vector addeventlistener


【解决方案1】:

您有一个成员变量模板侦听器,这意味着您对于每种函数类型都有一个向量。编译器无法推断您指的是哪一个。
您还尝试push_back 调用函数的结果,而不是函数本身,并且您没有存储参数。

您不能按照您计划的方式执行此操作,因为 listener 不是一个包含不同类型元素的变量——它(可能)是许多变量,每个变量都有不同的类型。
为了调用它们,您需要枚举变量实例化,这是不可能的。
此外,您还需要想办法存储参数。

由于你想稍后传递参数,你只需要一种类型,你可以在 lambda 中捕获它们:

class Button
{
public:
    Button(int _val):val(_val){}
    ~Button();
    int val;
    
    template<typename F, typename...InArgs>
    void addListener(std::function<F(InArgs...)> f, InArgs... args) {
        listener.push_back([=]() { f(args...); });
    }
    void action()
    {
        for (auto& f: listener)
            f();
    }
    void print() { std::cout << "Button value -> " << val << std::endl; }
    
private:
    static std::vector<std::function<void()>> listener;
    
};

std::vector<std::function<void()>> Button::listener;

void test3(Button* b) {
    
    std::cout << "listened:";
    b->print();
}

void test4(int a) {
    
    std::cout << "print " << a << std::endl;
}

int main()
{
    Button* button = new Button(5);
    button->print();
    button->addListener(std::function<decltype(test4)>(&test4), 1);
    button->addListener(std::function<decltype(test3)>(&test3), button);
    button->action();
}

您也可以将侦听器的构造完全留给用户:

class Button
{
public:
    Button(int _val):val(_val){}
    ~Button();
    int val;
    
    void addListener(std::function<void()> f) {
        listener.push_back(f);
    }
    void action()
    {
        for (auto& f: listener)
            f();
    }
    void print() { std::cout << "Button value -> " << val << std::endl; }
    
private:
    static std::vector<std::function<void()>> listener;
    
};

std::vector<std::function<void()>> Button::listener;

void test3(Button* b) {
    
    std::cout << "listened:";
    b->print();
}

void test4(int a) {
    
    std::cout << "print " << a << std::endl;
}

int main()
{
    Button* button = new Button(5);
    button->print();
    button->addListener([]() { test4(1); });
    button->addListener([button]() { test3(button); });
    button->action();
}

【讨论】:

  • 谢谢你的工作。我必须努力使用 decltypelambda
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多