将 std::vector::push_back 与 std::mem_fun 和 std::bind1st 一起使用

发布于 2024-09-15 20:22:11 字数 2345 浏览 9 评论 0原文

我正在尝试将 std::vector::push_backstd::mem_funstd::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 与它一起使用。

I'm trying to use std::vector<T*>::push_back with std::mem_fun and std::binder1st, but it doesnt seem to be feasible, can this be done?

I've tried to exemplify with the code below.

#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;
}

My goal is to have a container class to which I can tell it to execute a function receiving the selected items ('A' objects or 'A' derivate objects) as parameters. But I didn't manage to use std::vector::push_pack with it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽手叙旧 2024-09-22 20:22:11

问题是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)

换句话说,对a 的引用的引用指针。 C++ 中不存在对引用的引用。我能想到解决这个问题的唯一体面的方法是使用 boost::bind 代替:

vector<T*> ret;
Execute<T>( boost::bind( mem_fun(&vector<T*>::push_back), &ret,  _1) );
return ret;

还要注意你有一个错误,并且需要传递 bind &ret 而不是仅仅 ret (因为 mem_fun 需要一个指针,所以 mem_fun_ref 可以工作) )。

The problem is that binder1st defines operator() as:

operator() (const typename Operation::second_argument_type& x) const

and mem_fun1_t defines operator() as:

S operator() (T* p, A x) const

The problem is that push_back is defined as:

void vector<T>::push_back(const T &x)

So what we end up with is this:

void mem_fun1_t::operator()(vector<T *> *p, const T *&x)

And:

void binder1st::operator()(const T *&&x)

In other words, a reference to a reference to a pointer. A reference to a reference doesn't exist in C++. The only decent way I can think of fixing this is to use boost::bind instead:

vector<T*> ret;
Execute<T>( boost::bind( mem_fun(&vector<T*>::push_back), &ret,  _1) );
return ret;

Also note that you had a bug, and need to pass bind &ret instead of just ret (as mem_fun expects a pointer, mem_fun_ref would work however).

-残月青衣踏尘吟 2024-09-22 20:22:11

对容器中的整个项目集调用成员函数的最简单方法是使用 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
);

我不确定不过你想在这里实现什么。您同时具有编译时多态性(又名模板)和运行时多态性(又名虚拟成员函数)。设计似乎有点太复杂了。事实上,下面的定义就足够了:

int Execute()        
{
      int count = 0;
      for( int i=0; i< MyArraySize; ++i ){
          MyArray[ i ]->Foo(); // assume virtual int A::Foo(); exists
          ++count;
      }
      return count;
}

但是,正如您可能已经发现的那样,虚拟成员需要具有相同的签名才能在子类中被重写(否则您将重载该函数)。

请注意,示例 GetItems 不会调用所包含对象的成员函数,而是调用 vector 容器对象上的成员,即 push_back

如果您只想将指针从普通数组复制到矢量,您可以使用矢量的专用构造函数,该构造函数需要两个迭代器:

template<class T>
vector<T*> GetItems()  // <-- This is the problem function
{
    return vector<T*>( &MyArray[ 0 ], &MyArray[ 0 ] + MyArraySize );
}

The easiest way to call member functions on the entire set of items in your container is to use 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

If you don't have tr1 you can use:

for_each( cont.begin(), cont.end(), 
   bind2nd( mem_fun( &s::foo ), 42 ) // first parameter is the object itself
);

I am not sure what you are trying to achieve here though. You have both compile time polymorphism (aka templates) and runtime polymorphism (aka virtual member functions). The design seems a bit too complicated. In fact the following definition suffices:

int Execute()        
{
      int count = 0;
      for( int i=0; i< MyArraySize; ++i ){
          MyArray[ i ]->Foo(); // assume virtual int A::Foo(); exists
          ++count;
      }
      return count;
}

However, as you may have found out, virtual members need to have the same signature in order to be overriden in sub-classes (otherwise you are overloading the function).

Note that the sample GetItems does not call a member function of the contained objects, it calls a member, namely, push_back on the vector container object.

If all you want to do is to copy the pointers from a vanilla array to a vector you could use vector's specialized ctor that takes two iterators:

template<class T>
vector<T*> GetItems()  // <-- This is the problem function
{
    return vector<T*>( &MyArray[ 0 ], &MyArray[ 0 ] + MyArraySize );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文