具有不同参数的C ++ std :: function变量 [英] C++ std::function variable with varying arguments

查看:185
本文介绍了具有不同参数的C ++ std :: function变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的回调系统中,我想使用不同的参数存储 std :: function (或其他东西)。

In my callback system I want to store std::function (or something else) with varying arguments.

示例:


  1. 我想呼叫 void()

  2. 我要呼叫 void(int,int)

  1. I want to call void()
  2. I want to call void(int, int)

我想将1)和2)存储在同一个变量中,然后选择实际调用的内容

I want 1) and 2) to be stored in the same variable and choose what to call in actuall call

FunctionPointer f0;
FunctionPointer f2;

f0();
f2(4, 5);

是否可以这样做?或者我必须根据输入参数计数创建几个 FuntionPointer模板。

Is it possible to do something like this? Or I have to create several "FuntionPointer" templates based on input arguments count.

EDIT

是否可以将std :: bind用于此任务?使用std :: bind我可以拥有 std :: function< void()> f = std :: bind(test,2,5);

Is it possible to utilize std::bind somehow for this task? With std::bind I can have std::function<void()> f = std::bind(test, 2, 5);

编辑2

实际用例:我有一个触发器系统,我想为动作分配功能指针,所以当动作发生时,将调用函数。
伪代码示例:

Practical use case: I have a trigger system and I want to assign funtion pointers to actions, so when action happen, function is called. Pseudo-code sample:

structure Trigger 
{
   Function f;
}

Init:
  Trigger0.f = pointer to some function ()
  Trigger1.f = pointer to some function (a, b)

Input: 
  Find Trigger by input
  if (in == A) Trigger.f();
  else Trigger.f(10, 20)

或者如果可能的话

Input:
  Find Trigger by input
  if (in == A) f = bind(Trigger.f);
  else f = bind(Trigger.f, 10, 20);
  f()


推荐答案

好吧,如果可以使用RTTI,您可以像这样定义 MultiFuncObject ,并且可以轻松地绑定其他函数。另外,您可以轻松地致电给他们。但不幸的是,这种方法仅适用于有限数量的参数。但是实际上 boost :: bind 也支持有限数量的参数(默认为9)。因此,您可以扩展此类以满足您的需求。

Well, if you can use RTTI, you can define a MultiFuncObject like this, and you can easily bind other functions. Also, you can easily call them. But unfortunately, this approach only works for a limited number of arguments. But actually boost::bind also supports limited number of arguments (by default 9). So you can extend this class to satisfy your needs.

在为您提供 MultiFuncObject 的来源之前,向您展示如何使用它。它需要一个模板参数用作返回类型。您可以使用 + = 运算符绑定新函数。借助一些模板魔术,类可以区分具有至少一个不同参数类型的相同参数数量的绑定函数之间的差异。

Before giving you the source of MultiFuncObject, I want to show you how you can use it. It takes an template argument to be used as return type. You can bind new functions with += operator. With some template magic, the class distinguishes differences between bound functions with same count of arguments with at least one different argument type.

您需要C ++ 11,因为 MultiFuncObject 使用 std :: unordered_map std :: type_index

You need C++11, because MultiFuncObject uses std::unordered_map and std::type_index.

这里是用法:

#include <iostream>
using namespace std;

void _1() {
  cout << "_1" << endl;
}

void _2(char x) {
  cout << "_2" << " " << x << endl;
}

void _3(int x) {
  cout << "_3" << " " << x << endl;
}

void _4(double x) {
  cout << "_4" << " " << x << endl;
}

void _5(int a, int b) {
  cout << "_5" << " " << a << " " << b << endl;
}

void _6(char a, int b) {
  cout << "_6" << " " << a << " " << b << endl;
}

void _7(int a, int b, int c) {
  cout << "_7" << " " << a << " " << b << " " << c << endl;
}

int main() {
  MultiFuncObject<void> funcs;
  funcs += &_1;
  funcs += &_2;
  funcs += &_3;
  funcs += &_4;
  funcs += &_5;
  funcs += &_6;
  funcs += &_7;
  funcs();
  funcs('a');
  funcs(56);
  funcs(5.5);
  funcs(2, 5);
  funcs('q', 6);
  funcs(1, 2, 3);
  return 0;
}

我希望它接近您想要的。以下是 MultiFuncObject 的来源:

I hope this is close to what you want. Here is the source of MultiFuncObject:

#include <typeinfo>
#include <typeindex>
#include <unordered_map>

using namespace std;

template <typename R>
class MultiFuncObject {
  unordered_map<type_index, void (*)()> m_funcs;
public:

  MultiFuncObject<R> operator +=( R (* f)() ) {
    m_funcs[typeid( R() )] = (void (*)()) f;
    return *this;
  }

  template <typename A1>
  MultiFuncObject<R> operator +=( R (* f)(A1) ) {
    m_funcs[typeid( R(A1) )] = (void (*)()) f;
    return *this;
  }

  template <typename A1, typename A2>
  MultiFuncObject<R> operator +=( R (* f)(A1, A2) ) {
    m_funcs[typeid( R(A1, A2) )] = (void (*)()) f;
    return *this;
  }

  template <typename A1, typename A2, typename A3>
  MultiFuncObject<R> operator +=( R (* f)(A1, A2, A3) ) {
    m_funcs[typeid( R(A1, A2, A3) )] = (void (*)()) f;
    return *this;
  }

  R operator()() const
  {
    unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R() ));
    if (it != m_funcs.end()) {
      R (*f)() = ( R (*)() )(it->second);
      (*f)();
    }
  }

  template <typename A1>
  R operator()(A1 a1) const
  {
    unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1) ));
    if (it != m_funcs.end()) {
      R (*f)(A1) = ( R (*)(A1) )(it->second);
      (*f)(a1);
    }
  }

  template <typename A1, typename A2>
  R operator()(A1 a1, A2 a2) const
  {
    unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2) ));
    if (it != m_funcs.end()) {
      R (*f)(A1, A2) = ( R (*)(A1, A2) )(it->second);
      (*f)(a1, a2);
    }
  }

  template <typename A1, typename A2, typename A3>
  R operator()(A1 a1, A2 a2, A3 a3) const
  {
    unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2, A3) ));
    if (it != m_funcs.end()) {
      R (*f)(A1, A2, A3) = ( R (*)(A1, A2, A3) )(it->second);
      (*f)(a1, a2, a3);
    }
  }

};

它使用 std :: unordered_map ,其键为 std :: type_index ,值为 void(*)()

It stores different function prototypes using std::unordered_map with keys of std::type_index and values of void (*)(). When needed, the correct function is retrieved using that map.

此处为工作示例

这篇关于具有不同参数的C ++ std :: function变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆