C++ 不同函子的容器
我正试图找到一种方法来拥有一个函子容器,这样我就可以将一个值传递到函子中并对其进行修改。然而,我在允许函子不受限制地传递它们的类型和它们可以接受的参数数量方面遇到了困难 我的实际用途是,我有一系列的函子,它们都会根据输入以某种方式改变3D向量。通过将这些函子存储在一个容器中,我可以控制调用它们的顺序,并通过在容器上迭代并将每个函子传递给向量,最终得到一个不同的结果向量。我用这些向量来确定粒子的位置,颜色,加速度等等。因此,通过采用这种模块化方法,最终我可以创建截然不同的粒子效果,最终我可以在运行时通过文件定义函子顺序。这是我的最终目标:) 我完成这项工作的唯一方法是使用继承和一堆无效指针,这使得代码极难遵循、调试和使用 这里是我迄今为止的代码,希望它能证明我正在努力做的比我上面键入的更好。请注意,我已经远远超出了我的舒适区,所以这段代码可能很可怕,让你们中的一些大师想用棍子打我C++ 不同函子的容器,c++,containers,void-pointers,C++,Containers,Void Pointers,我正试图找到一种方法来拥有一个函子容器,这样我就可以将一个值传递到函子中并对其进行修改。然而,我在允许函子不受限制地传递它们的类型和它们可以接受的参数数量方面遇到了困难 我的实际用途是,我有一系列的函子,它们都会根据输入以某种方式改变3D向量。通过将这些函子存储在一个容器中,我可以控制调用它们的顺序,并通过在容器上迭代并将每个函子传递给向量,最终得到一个不同的结果向量。我用这些向量来确定粒子的位置,颜色,加速度等等。因此,通过采用这种模块化方法,最终我可以创建截然不同的粒子效果,最终我可以在运行
#include <iostream>
#include <vector>
//the base functor class
struct Functor {
//an integer so we can tell how many arguments the functor takes
unsigned num_arguments;
Functor() : num_arguments(0) {}
//I'm making the arguments default to 0 so the compiler doesn't complain about not giving enough arguments
virtual void operator()(void* R, void* A1 = 0, void* A2 = 0, void* A3 = 0) = 0;
};
template<typename R, typename A1>
struct Double : public Functor {
Double() { num_arguments = 1; }
void operator()(void* i, void* a, void*, void*) {
//having to cast everything out of void pointers so it can be used
A1& first = *static_cast<A1*>(a);
*static_cast<R*>(i) = first * 2;
}
};
template<typename R, typename A1, typename A2>
struct Sub : public Functor {
Sub() { num_arguments = 2; }
void operator()(void* i, void* a, void* b, void*) {
//having to cast everything out of void pointers so it can be used
A1& first = *static_cast<A1*>(a);
A2& second = *static_cast<A2*>(b);
*static_cast<R*>(i) = first - second;
}
};
int main() {
//our container for the functors
std::vector<Functor*> functors;
functors.push_back(new Double<int, int>);
functors.push_back(new Sub<int, int, int>);
for(int i = 0; i < functors.size(); ++i) {
int result;
int first = 1, second = 2;
Functor& f = *functors[i];
if(f.num_arguments == 1) {
f(&result, &first);
} else if(f.num_arguments == 2){
f(&result, &first, &second);
}
std::cout << result << std::endl;
}
Functor* float_sub = new Sub<float, float, float>;
float result;
float first = 0.5f, second = 2.0f;
(*float_sub)(&result, &first, &second);
std::cout << result << std::endl;
functors.push_back(float_sub);
//The functors vector now contains 3 different types of functors:
//One that doubles an integer
//One that subtracts two integers
//One that subtracts two floats
std::cin.get();
return 0;
}
现在我终于有机会投票了:你有没有想过使用?我不确定这是一个更好的解决方案,但它是不同的。例如:
#include <vector>
#include <cstdarg>
#include <iostream>
using namespace std;
template< typename type >
void sub( void* out, ... ){
// Initialize the variadic argument list.
va_list args;
va_start( args, out );
// Extract our arguments.
type lhs = va_arg( args, type );
type rhs = va_arg( args, type );
// Close the variadic argument list.
va_end( args );
// Function logic goes here.
*(static_cast<type*>(out)) = lhs - rhs;
}
int main( void ){
typedef void (*functor)( void* out, ... ); // Function type.
typedef vector< functor > FunctorList; // Function list type.
FunctorList fList;
fList.push_back( &sub<int> );
int diff;
fList[0]( &diff, 3, 5 );
cout << diff << endl;
return 0;
}
#包括
#包括
#包括
使用名称空间std;
模板<类型名称类型>
作废子项(作废*作废,…){
//初始化可变参数列表。
va_列表参数;
va_启动(args,out);
//摘录我们的论点。
类型lhs=va_arg(args,类型);
类型rhs=va_arg(args,类型);
//关闭可变参数列表。
va_端(args);
//函数逻辑在这里。
*(静态_cast(out))=左侧-右侧;
}
内部主(空){
typedef void(*函子)(void*out,…);//函数类型。
typedef向量FunctorList;//函数列表类型。
函数列表列表;
fList.push_back(&sub);
int-diff;
fList[0](&diff,3,5);
cout我没有意识到您特别想要函数对象(应该使用“functor”而不是“函数指针”来单击)。无论如何,这是我以前使用函数对象的答案。它的工作原理是一样的:
#include <vector>
#include <cstdarg>
#include <iostream>
using namespace std;
struct FunctorBase {
virtual void operator()( void* out, ... ) = 0;
}; // end FunctorBase
template< typename T >
struct Subtract : public FunctorBase {
void operator()( void* out, ... ){
// Initialize the variadic argument list.
va_list args;
va_start( args, out );
// Extract our arguments
T lhs = va_arg( args, T );
T rhs = va_arg( args, T );
// Close the variadic argument list.
va_end( args );
// Function logic goes here.
*(static_cast<T*>(out)) = lhs - rhs;
}
};
int main( void ){
typedef vector< FunctorBase* > FunctorList; // Function list type.
FunctorList fList;
fList.push_back( new Subtract<int>() );
int diff;
(*fList[0])( &diff, 3, 5 );
cout << diff << endl;
return 0;
}
#包括
#包括
#包括
使用名称空间std;
结构函子基{
虚拟void运算符()(void*out,…)=0;
};//结束FunctorBase
模板
结构减去:公共FunctorBase{
void运算符()(void*out,…){
//初始化可变参数列表。
va_列表参数;
va_启动(args,out);
//摘录我们的论点
T lhs=va_arg(args,T);
T rhs=va_arg(args,T);
//关闭可变参数列表。
va_端(args);
//函数逻辑在这里。
*(静态_cast(out))=左侧-右侧;
}
};
内部主(空){
typedef vectorFunctorList;//函数列表类型。
函数列表列表;
fList.push_back(新减法());
int-diff;
(*fList[0])(&diff,3,5);
更好的问题是“你想用这个实现什么?”。你可以通过使用指向函数的指针来实现这一点?存储它们?@CatPlusPlus如果不清楚,很抱歉,我正在寻找一种更好的方法来实现上述代码的功能,或者是否有更好的方法。这不是问题。你想要它做什么?请仔细查看一下的问题,特别是;我记得他一直在寻求这一功能,他似乎报告他在那个答案中发现了一些东西。还没有检查出来,但你可能很感兴趣。varargs
在被成员函数使用时似乎表现得很奇怪,至少对我来说是这样。试着把你的sub
函数变成一个函子。@Rarge:我相信你的编辑建议是错误的——我的文档说明参数last
是变量参数列表之前的最后一个参数的名称,即调用函数知道其类型的最后一个参数。您可能应该使用out
代替2
,但我可能会在这一点上弄错。(我也不认为函数的第一个参数应该是一个void*
,但我可能在这一点上又弄错了。)@Oz,va_start的第二个参数应该是已知类型的最后一个参数,out
。ref:。你说得对吗:).显示了我使用stdarg.h的频率。奇怪的是,它仍然可以很好地与GCC配合使用。@sarnold哦,我想我现在明白了。我误解了va_start。我认为第二个参数是函数的参数数,而不是变量参数列表前的最后一个参数。当我运行这个时,输出不是预期的-2,而不是-2我得到了-862661424,这是我在上一篇评论中试图说的。va_args似乎在成员函数中表现得很糟糕?Hrm,我在Ubuntu上使用GCC 4.4.3编译它,它工作得很好,输出-2。你在使用什么编译器?你得到了什么错误?不管怎样,输出是因为我误解了va_start。e这个版本很好用。
#include <vector>
#include <cstdarg>
#include <iostream>
using namespace std;
struct FunctorBase {
virtual void operator()( void* out, ... ) = 0;
}; // end FunctorBase
template< typename T >
struct Subtract : public FunctorBase {
void operator()( void* out, ... ){
// Initialize the variadic argument list.
va_list args;
va_start( args, out );
// Extract our arguments
T lhs = va_arg( args, T );
T rhs = va_arg( args, T );
// Close the variadic argument list.
va_end( args );
// Function logic goes here.
*(static_cast<T*>(out)) = lhs - rhs;
}
};
int main( void ){
typedef vector< FunctorBase* > FunctorList; // Function list type.
FunctorList fList;
fList.push_back( new Subtract<int>() );
int diff;
(*fList[0])( &diff, 3, 5 );
cout << diff << endl;
return 0;
}