2013-03-13 58 views
2

可以编写一个包含支持特定操作的任何类型的包装器,用于二进制操作的类型擦除

#include <iostream> 

class Houdini 
{ 
    struct I_Houdini_Impl 
    { 
    virtual void foo_impl(int x) const = 0; 

    virtual ~I_Houdini_Impl() { } 
    }; 

    template <typename T> 
    struct Houdini_Impl : I_Houdini_Impl 
    { 
    Houdini_Impl(T const & t) : m_t(t) { } 

    void foo_impl(int x) const { m_t.foo(x); } 

    T m_t; 
    }; 
public: 
    template <typename T> 
    Houdini(T const & t) : m_impl(new Houdini_Impl<T>(t)) { } 

    void foo(int x) const { m_impl->foo_impl(x); } 
protected: 
private: 

    std::unique_ptr<I_Houdini_Impl> m_impl; 
}; 

class A 
{ 
public: 
    void foo(int x) const { std::cout << "A::foo(" << x << ")" << std::endl; } 
}; 

class B 
{ 
public: 
    template <typename T> 
    char foo(T const & t) const { std::cout << "B::foo(" << t << ")" << std::endl; return 'B';} 
}; 

void houdini() 
{ 
    A a; 
    B b; 
    Houdini ha(a); 
    Houdini hb(b); 

    ha.foo(7); 
    hb.foo(8); 
} 

我可以在支持可称为王氏一个int一个const-方法foo的霍迪尼级包裹任何事情,如果无论它是一个普通的成员函数(如类A)或函数模板(如B类)(现在让我们忽略Houdini应该展示价值语义)。到目前为止这么好,但我想要做的是编写一个支持二进制操作的包装器,例如写一个可以接受任何类型的包装,你可以说,只要包装的对象可以被添加,并返回从将包裹返回对象添加任何两种包装:如果我知道

class A { }; 
class B { }; 
class C { }; 

C operator+(A, B) { return C(); } 

class Randi 
{ 
public: 
    template <typename T> Randi(T) { } 

/* magic stuff goes here */ 
}; 

void randi() 
{ 
    A a; 
    B b; 

    Randi ra(a); 
    Randi rb(b); 

    Randi rc = ra + rb; 
    // rc is a Randi-object that wraps an object of type C 
} 

事先什么类型我要去存储我可以通过写访问来做到这一点,但这正是我所做的而不是想要做的。我需要解开这两个对象,试着在两个打开的对象上调用operator +并重新包装结果,但我无法弄清楚如何做到这一点。

+0

我会说,与模板和魔术这可以解决,但我不够聪明,知道如何。 – 2013-03-13 14:10:23

+0

根据你目前的描述,我想你可能会走运。确定使用'operator +'的哪些可能的重载将需要编译时知道所涉及的类型,但是您已经专门擦除了该类型的信息。如果两个操作数必须是相同的类型,您可能可以做到这一点。 – 2013-03-13 17:13:26

回答

0

考虑以下

class Number 
{ 
virtual Number* sum(Number* other) = 0; 
}; 

class Int 
    : public Number 
{ 
    virtual Number* sum(Number* other) 
    { 
     // hard to implement since we doesn't know the type of other 
    } 
}; 


class Double 
    : public Number 

{ 
    virtual Number* sum(Number* other) 
    { 
     // hard to implement since we doesn't know the type of other 
    } 
}; 

我们可以做dynamic_casts总之执行单独处理每种情况下,我们也可以使用双调度。

class Double; 
class Int; 

class Number 
{ 
public: 
    virtual Number* sum(Number* other) = 0; 
protected 
    virtual Number* sum(Int* other) = 0; 
    virtual Number* sum(Double* other) = 0; 
}; 

class Int 
    : public Number 
{ 
    virtual Number* sum(Number* other) 
    { 
     return other->sum(this); 
    } 

    virtual Number* sum(Int* other) 
    { 
     // implement int + int 
    } 

    virtual Number* sum(Double* other) 
    { 
     // implement int + double 
    } 
}; 


class Double 
    : public Number 

{ 
    virtual Number* sum(Number* other) 
    { 
     return other->sum(this); 
    } 


    virtual Number* sum(Int* other) 
    { 
     // implement double + int 
    } 

    virtual Number* sum(Double* other) 
    { 
     // implement double + double 
    } 
}; 

在bot情况下,实现应该知道所有派生类。这意味着类似于Randi类的Houdini_Impl应该知道可能传递给Randi构造函数的所有其他类型,这是不可能的。

相关问题