【问题标题】:How to call a function(only known at runtime) with parameter values(only known at runtime)?如何使用参数值(仅在运行时知道)调用函数(仅在运行时知道)?
【发布时间】:2020-11-02 14:33:01
【问题描述】:

在运行时进行一次测试以确定调用两个函数中的哪一个并建立参数值。

然后每隔几秒调用一次函数。

void Foo::func( std::string s);
void Foo::func( std::string s1 std::string s2, std::string s2);

显然,每次调用都测试(调用哪个函数)效率低下,尤其是当函数及其参数值一旦建立就不会改变时。

我需要这样的东西:

测试一次调用哪个函数并建立参数值。

将初始化函数分配给某种可调用变量。

funcVar = void Foo::func( "blah", "blah", "woof" );

funcVar = void Foo::func( "blah" );

然后调用函数;

for( every few seconds )
{
call FuncVar;
}

我可以使用某种可调用变量来执行此操作吗?

【问题讨论】:

  • std::function?
  • 你可以使用 std::bind 吗?
  • 我会使用enum 来存储测试结果(或boolean)并使用switch / if else 包含for 循环,每个循环都有它们的特定功能- 因为所有函数重载在运行时之前都是已知的。
  • 如果一开始就知道字符串参数,您可以将它们绑定到 std::function,然后稍后将其作为不带参数的函数调用。 godbolt.org/z/Y3xPea
  • 假设唯一的输入是truefalse。现在,您需要做的就是在其上创建一个if 测试,这样如果测试成功,它将开始循环使用预设变量的函数。否则,它将循环使用预设变量的另一个函数。但是,我不知道 std::functionstd::bind 存在,但它们似乎更好 (C++) 解决方案;我的算法是适用于任何语言的通用算法。

标签: c++ call std-function


【解决方案1】:

您可以简单地使用一个 lambda 函数对象(闭包),您可以随意调用它。

例子:

struct Foo 
{
    void func( std::string s){ std::cout << "single" << s << std::endl; };
    void func( std::string s1, std::string s2, std::string s3) 
    {   
        std::cout << "tripple " << s1 << " " << s2 << " " << s3 << std::endl;
    }   

    // Select which function to call
    std::function<void()> Select( int what )
    {   
        if ( what == 1 )
        {   
            // Create a callable object and put in also parameters
            return [this]() { func("Hallo"); };
        }
        else
        {   
            // The same for the other selection
            return [this]() { func("This","is","tripple!"); };
        }
    }   
};  

int main()
{   
    Foo foo;
 
    // Pick what you want to select
    auto action = foo.Select( 2 );

    for ( ;; )
    {   
        // and call it as often you like
        action();
    }   
}

【讨论】:

  • 在 Klaus 和 Werner 的回答之间是一个紧密的事情,但 lambda 语法似乎更简单明了..我从所有各种答案/cmets 中学到了一些东西。
【解决方案2】:

您可以使用std::bind 为您的两个用例创建一个带有存储参数和通用调用运算符的函子。检查这个sn-p:

#include <string>
#include <functional>

struct Foo {
    static void a(std::string) {}
    static void b(std::string, std::string) {}
};

int main() {
    std::function<void()> x;

    if(true) {
        x = std::bind(&Foo::b, "a", "b");
    }

    x();

    return 0;
}

【讨论】:

  • 这不会重载对象的函数
  • 问的问题不是关于重载函数,而是如何分配给变量不同的可调用对象,然后在不做检查的情况下调用它。所以我已经为这个问题添加了答案。
  • LearnMore 提到了 Foo:foo(std::string) 和 Foo:foo(std::string, std::string) 并且他想调用这两个重载函数之一。
  • 不过,我相信这与其说是一段真正的代码,不如说是对提问者需求的元句法表达,而且问题的精神是关于存储可调用对象。如果这个答案没有用,其他的都会被接受,没什么大不了的。
  • 真正的代码确实涉及重载函数,但是 Jakub 的回答增加了我的理解
【解决方案3】:

如果你想 std::bind 重载函数,你必须指定你想使用哪一个:

#include <string>
#include <functional>
#include <iostream>
#include <map>


struct Foo {
    void b() { std::cout << name << ": function 1" << std::endl; }
    void b(int i) {std::cout << name << ": function 2" << std::endl; }

    std::string name;
};


void with_map() {
    Foo f;
    f.name = "with_map";

    std::map<const int, std::function<void()>> map({
        {10, std::bind<void(Foo::*)(), Foo&>(&Foo::b, f)},
        {20, std::bind<void(Foo::*)(int), Foo&, int>(&Foo::b, f, 1)},
    });

    map[20]();
    map[10]();
}


void without_map() {
    Foo f;
    f.name = "without_map";

    std::function<void()> x = std::bind<void(Foo::*)(), Foo&>(&Foo::b, f);
    x();

    x = std::bind<void(Foo::*)(int), Foo&, int>(&Foo::b, f, 1);
    x();
}


int main() {

    without_map();

    with_map();

    return 0;
}

【讨论】:

    【解决方案4】:

    std::function 应该在这里工作。

    std:: function<void()> fun = [&s] () {/* do  work*/};
    if (some_condition)
    {
       fun = [&s1,&s2,&s3] () {/* do your work*/} ;
    }
    
    if(every few seconds)
    {
        fun();
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-10
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-05
      • 2016-07-27
      相关资源
      最近更新 更多