使用以前未知的模板存储通用对象

Store a generic object with previously unknown template

本文关键字:存储 对象 未知      更新时间:2023-10-16

我正在尝试用c ++创建某种事件处理程序。所以我有以下几点:

template<class W> 
delegate<W>* bind(W* obj, void (W::*f)(char*))
{
        return new delegate<W>(obj,f);
}

委托类和此函数完美运行。问题是如何存储带有绑定函数返回的委托对象?我知道使用 boost 和 c++ 11 很容易,但是如何在不使用它们的情况下解决这个问题?我确信它一定是可能的,因为在 boost 和 c++11 等复杂的东西之前它是可能的。

(他们也以某种方式在提升中做到了)。

所以我想做的是:

class Test1
{
    Test1(){}
    ~Test1(){}
    template<class W> 
    bind(W* obj, void (W::*f)(char*))
    {
            myCallBack = new delegate<W>(obj,f);
    }
    private:
        delegate * myCallBack;  //this does not work because I have to define the template but I dont know it know it could be anything
}
class Test2
{
    Test2()
    {
        Test1 t;
        t.bind(this, &Test2::callit);
    }
    ~Test2(){}
    void callit(char*)
    {
    }
}

好的,我明白你到底需要什么。您只需要一个简单的回调运算符,具有固定的调用签名。

此示例演示了如何针对您的特定情况完成此操作:

#include <iostream>
#include <utility>
#include <type_traits>
#include <vector>
#include <algorithm>

struct Cb {
    virtual ~Cb(){}
    virtual void call(const char*) = 0;
};
template<class C>
struct CmCb : Cb {
    CmCb( C& c_, void (C::*fn_)(const char*) ) : c(c_),fn(fn_)
    {
    }
    virtual void call(const char* s) {
        (c.*fn)(s);
    }
    C& c;
    void (C::*fn)(const char*);
};
struct A {
    void foo( const char* s ) {
        std::cout<<s<<std::endl;
    }
};
class Test1
{
public:
    Test1(){}
    ~Test1(){delete cb;}
    template<class W> 
    void bind(W* obj, void (W::*f)(const char*))
    {
            cb=new CmCb<W>(*obj,f);
    }
    
    void callit(const char* s ){
        cb->call(s);
    }
    private:
        Cb* cb;
};
int main()
{
    Test1 t;
    
    A a;
    t.bind(&a, &A::foo );
    
    t.callit("hey");
}
<小时 />

如果您需要更复杂的解决方案(通用签名),则可以使用带有 boost::any 的某种类型擦除。

确实有比原始标准(std::auto_ptr)提供的更复杂的智能指针实现。但它们都涉及更复杂的概念(主要是关于共享指针的引用计数)。使用这些的障碍是什么?

如果您需要为 c++03 环境提供更轻量级的智能指针实现,Andrei Alexandrescu 的 Loki 库可能对您有用。我已经设法至少在有限的系统环境中无缝集成了它(比使用 boost 更好、更容易)。

甚至不要尝试完全靠自己做到这一点,有很多很多陷阱......如果您能够启用 c++11 标准,只需使用这些标准!