5

我目前正在用 C++x0 编写方法执行队列。我已经实现并验证了基本队列机制,但想通过一个选项对其进行修改,以push()自动删除所有先前对特定方法的调用:

queue.push(this, &Obj::foo, 1);
queue.push(this, &Obj::foo, 2);
queue.push(this, &Obj::foo, 3);

应该与仅调用相同

queue.push(this, &Obj::foo, 3);

到目前为止,我的代码如下所示:

队列.h:

#pragma once

#include <functional>
#include <vector>

using std::vector;
using std::function;
using std::bind;

class Queue
{

    private:
        struct functioncall {
            std::function<void()> call;
        };

        vector<functioncall> queue;

    public:
        Queue();
        ~Queue();

        template<typename T, typename F, typename... Args>
        int push(T, F , Args... args);

        int pop();
        bool empty();
        size_t size();
};


template<typename T, typename F, typename... Args>
int Queue::push(T instance, F func, Args... args)
{
    functioncall newelem = { bind(func, instance, args...) };
    queue.push_back(newelem);
    return queue.size();
}

队列.cpp:

#include "Queue.h"

Queue::Queue() : queue()
{
}

Queue::~Queue()
{
    delete &queue;
}

int Queue::pop()
{
    if(!queue.empty())
    {
        queue.front().call();
        queue.erase(queue.begin());
        return queue.size();
    }
    return 0;
}

bool Queue::empty()
{
    return queue.empty();
}

size_t Queue::size()
{
    return queue.size();
}

我已经准备好向量queue来获取一个结构,我不仅要保存结果,std::bind还要保存指向被调用方法的指针,这样我就可以查找该指针并删除旧条目。

问题是传递给的函数push()可以接受任意数量的参数。是否有可以做到这一点的通用指针类型(它不必是可执行的,只是当我重复将相同的函数推送到队列时相同)?

4

2 回答 2

5

根据 5.2.10p10,您可以将指向成员函数的指针转换T::*(A1, A2, ...)为指向成员函数类型的另一个指针U::*(B1, ...)并返回,而不会丢失信息;std::less可以比较指向成员函数的指针,因此通过转换为指向成员的虚拟指针类型void (Impl::*)(),您可以比较指向具有相同签名的成员函数的指针。

但是,不能保证指向具有不同签名的成员函数的指针在转换为指向相同成员类型的指针时会比较不同,因此您需要在可比较类型中对签名进行编码。 typeid将在这里工作:

auto key = std::make_pair(&typeid(F), reinterpret_cast<void (Queue::*)()>(func));

这假设这F确实是一个指向成员函数的指针;如果用户尝试传递一些其他可调用对象,那么这将中断。

于 2012-11-29T09:51:05.553 回答
3

std::function::target<>()可用于检查包装函数类型:

template <class F> bool is_same_call(const functionalcall& prevCall, F newCall)
{
   const F* pf = prevCall.call.target<F>();
   return pf ? *pf == newCall : false;
}

请注意,如果用 object 包装的函数std::function::target()的类型不同于.nullptrstd::functionF

于 2012-11-29T10:50:49.717 回答