【问题标题】:Replacing templated function pointer by generic type用泛型类型替换模板化函数指针
【发布时间】:2012-11-20 08:45:05
【问题描述】:

我为std::bindstd::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-&gt;push&lt;int&gt;(&amp;Object::jumpAround, 10);queue-&gt;pop())。问题是,我找不到一个通用的对象和函数指针,使我能够在没有&lt;class T&gt; 模板的情况下实现它。

我知道在这里使用模板可能是最安全和最好的方法,但由于实现此队列的代码设计,我需要摆脱它。有什么想法吗?

我想这一定是可能的,因为std::bind 的第一个参数可以是任何函数,第二个参数可以是任何对象。

【问题讨论】:

  • 如果你使用std::bind你有C++11,那你为什么不使用std::function呢?
  • 我唯一使用它的地方是在我的队列定义中:std::queue&lt;std::function&lt;void()&gt;&gt; queue;。我不知道我还能/应该在哪里使用它...

标签: c++ templates pointers


【解决方案1】:

如果我理解,以下是您需要的:

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));

【讨论】:

  • 这不是要求我在我的实现代码中“找出指针的肮脏之处”,选择正确的模板值等吗?
  • @NilsWerner,不,编译器会为你推断出所有这些东西。上面的代码应该按原样工作 - 无论你传入什么......
  • 看起来不错,但我的代码的其他部分已损坏,所以一旦我找出仍然缺少的内容并验证您的解决方案有效,我将批准您的回答 :-)
猜你喜欢
  • 2021-03-14
  • 2018-12-04
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
相关资源
最近更新 更多