我正在尝试将std::vector<T*>::push_back
与std::mem_fun
和std::binder1st
一起使用,但它似乎不可行,可以这样做吗?
我试图用下面的代码举例说明。
#include <vector>
#include <functional>
#include <iostream>
using namespace std;
struct A {
int _Foo;
virtual int AFoo() { return _Foo; };
};
struct B: public A {
int BFoo(int bar) { return _Foo+bar ; };
};
struct C: public A {
int CFoo() { return --_Foo; };
};
class MyContainer
{
static const int MyArraySize = 100;
A* MyArray[MyArraySize];
public:
MyContainer() {
int half = MyArraySize / 2;
for( int i=0; i< half; ++i )
MyArray[i] = new B;
for( int i=half; i < MyArraySize; ++i )
MyArray[i] = new C;
}
template<class T, class Fn1>
int Execute( Fn1 func )
{
int count = 0;
for( int i=0; i< MyArraySize; ++i ){
T* t = dynamic_cast<T*>(MyArray[i]);
if( t )
{
func(t);
++count;
}
}
return count;
}
template<class T, class Res, class Arg>
int Execute( mem_fun1_t<Res, T, Arg> func, Arg argument )
{
return Execute<T>( binder2nd< mem_fun1_t<Res,T,Arg> >( func, argument ) );
}
template<class T>
vector<T*> GetItems() // <-- This is the problem function
{
vector<T*> ret;
Execute<T>( bind1st( mem_fun(&vector<T*>::push_back), ret ) );
return ret;
}
};
int main( int argc, char* argv[] )
{
MyContainer cont;
cont.Execute<B>( mem_fun(&B::BFoo), 10 );
cont.Execute<C>( mem_fun(&C::CFoo) );
vector<B*> v = cont.GetItems<A>(); // <-- the problem function is called here.
cout << "v.size = " << v.size() << endl;
}
我的目标是拥有一个容器类,我可以告诉它执行接收所选项('A'对象或'A'派生对象)作为参数的函数。但我没有设法使用std::vector::push_pack
。
答案 0 :(得分:1)
在容器中的整个项目集上调用成员函数的最简单方法是使用for_each
:
using namespace std;
using namespace std::tr1;
vector<T> cont;
// ...
for_each( cont.begin(), cont.end(),
bind( &T::foo, 42 ) );
// assume void T::foo(int); exists
如果您没有tr1
,可以使用:
for_each( cont.begin(), cont.end(),
bind2nd( mem_fun( &s::foo ), 42 ) // first parameter is the object itself
);
我不确定你在这里想要达到的目标。你有编译时多态(aka模板)和运行时多态(aka virtual
成员函数)。设计看起来有点过于复杂。实际上,以下定义就足够了:
int Execute()
{
int count = 0;
for( int i=0; i< MyArraySize; ++i ){
MyArray[ i ]->Foo(); // assume virtual int A::Foo(); exists
++count;
}
return count;
}
但是,正如您可能已经发现的那样,virtual
成员需要具有相同的签名才能在子类中重写(否则您正在重载该函数)。
请注意,示例GetItems
不会调用包含对象的成员函数,它会调用成员,即push_back
容器对象上的vector
。
如果您只想将指针从vanilla数组复制到vector
,那么您可以使用vector
专门的ctor来获取两个迭代器:
template<class T>
vector<T*> GetItems() // <-- This is the problem function
{
return vector<T*>( &MyArray[ 0 ], &MyArray[ 0 ] + MyArraySize );
}
答案 1 :(得分:1)
问题是binder1st将operator()定义为:
operator() (const typename Operation::second_argument_type& x) const
和mem_fun1_t将operator()定义为:
S operator() (T* p, A x) const
问题是push_back定义为:
void vector<T>::push_back(const T &x)
所以我们最终得到的是:
void mem_fun1_t::operator()(vector<T *> *p, const T *&x)
和
void binder1st::operator()(const T *&&x)
换句话说,对指针的引用的引用。 C ++中不存在对引用的引用。我能想到解决这个问题的唯一方法就是使用boost :: bind代替:
vector<T*> ret;
Execute<T>( boost::bind( mem_fun(&vector<T*>::push_back), &ret, _1) );
return ret;
另请注意,您有一个错误,需要传递bind&amp; ret而不仅仅是ret(因为mem_fun需要一个指针,mem_fun_ref会起作用)。