具有不同参数的C ++ std :: function变量 [英] C++ std::function variable with varying arguments
问题描述
在我的回调系统中,我想使用不同的参数存储 std :: function
(或其他东西)。
In my callback system I want to store std::function
(or something else) with varying arguments.
示例:
- 我想呼叫
void()
- 我要呼叫
void(int,int)
- I want to call
void()
- 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 $ c $存储不同的函数原型c>,其键为
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屋!