C ++ 11中的通用函数指针

时间:2012-11-29 09:32:58

标签: c++ c++11 function-pointers

我目前正在用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);

到目前为止我的代码看起来像这样:

Queue.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();
}

Queue.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()的函数可以采用任意数量的参数。是否存在通用指针类型(它不必是可执行的,当我反复将相同的函数推送到队列时是相同的)可以做到这一点?

2 个答案:

答案 0 :(得分:4)

根据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确实是指向成员函数的指针;如果用户试图传递一些其他可调用对象,那么这将会中断。

答案 1 :(得分: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;
}

请注意,如果使用std::function::target()对象包装的函数的类型与nullptr不同,则std::function将返回F