2

と の次のラッパーを作成std::bindしましたstd::queue

#include "Queue.h"

template<class T>
Queue<T>::Queue(T* input)
{
    instance = input;
}

template<class T> template<typename... Args>
int Queue<T>::push(int (T::*func)(Args... args), Args... args)
{
    queue.push(std::bind(func, instance, args...));
    return queue.size();
}

template<class T>
int Queue<T>::pop()
{
    if(!queue.empty())
    {
        queue.front()();
        queue.pop();
        return queue.size();
    }
    return 0;
}

template<class T>
bool Queue<T>::empty()
{
    return queue.empty();
}

template<class T>
size_t Queue<T>::size()
{
    return queue.size();
}

次のヘッダーを使用します。

#ifndef QUEUE_H_
#define QUEUE_H_

#include <functional>
#include <queue>

template <class T>
class Queue
{
    private:
        std::queue<std::function<void()>> queue;    /**< the messaging queue, appended to using enqueue(), popped from using dequeue() */
        T* instance;

    public:

        Queue(T*);

        template<typename... Args>
        int enqueue(int (T::*f)(Args... args), Args... args);

        int dequeue();

        bool empty();

        size_t size();
};

#endif

バインドされた関数式をキューに追加し、後でそれらをポップできます ( queue->push<int>(&Object::jumpAround, 10);and queue->pop())。<class T>問題は、テンプレートなしでこれを実装できる汎用オブジェクトおよび関数ポインターが見つからなかったことです。

ここではテンプレートを使用するのがおそらく最も安全で最善の方法であることはわかっていますが、このキューを実装するコードの設計により、これを取り除く必要があります。何か案は?

std::bindの最初のパラメーターは任意の関数にすることができ、2 番目のパラメーターは任意のオブジェクトにすることができるため、何らかの形で可能であるに違いないと思います。

4

1 に答える 1

3

私が理解した場合、以下はあなたが必要とするものです:

class Queue
{
private:
  std::queue<std::function<void()>> queue;    /**< the messaging queue, appended to using enqueue(), popped from using dequeue() */
public:

  // pass in the instance of the object and simply allow the compiler to deduce the function pointer nastiness...
  template<typename T, typename F, typename... Args>
  void enqueue(T instance, F func, Args... args)
  {
    queue.push(std::bind(func, instance, args...));
  }

  int dequeue()
  {
    if(!queue.empty())
    {
      queue.front()();
      queue.pop();
    }
  }
};

ああ、それを使用する方法:

struct foo
{
  void bar(int a)
  {
    std::cout << "foo::bar: " << a << std::endl;
  }
};

struct bar
{
  void foo(int a, int c)
  {
    std::cout << "bar::foo: " << (a  + c)<< std::endl;
  }
};

int main(void)
{
  Queue q;
  foo f;
  bar b;
  q.enqueue(&f, &foo::bar, 10);
  q.enqueue(&b, &bar::foo, 10, 11);

  q.dequeue();
  q.dequeue();
}

出力する必要があります:

foo::bar: 10
bar::foo: 21

または、さらに良いことに、関数のシグネチャを変更して、ユーザーがstd::function! これが「通常の」方法です (たとえば、 を参照してくださいboost::asio::io_service::post)。

編集: これは簡単な例です:

// Let the compiler do all the hard work for you..
template<typename T>
void enqueue(T f)
{
  queue.push(f);
}

関数をこのキューにポストするには...

// Here you are posting the functor itself...
q.enqueue(std::bind(&bar::foo, &b, 15, 12));
于 2012-11-20T09:12:26.557 に答える