可以编写一个包含任何支持某种操作的类型的包装器,例如
#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);
}
我可以在Houdini类中包装任何支持const-method foo的东西,可以用int调用它,无论它是普通的成员函数(如在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 :(得分: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
}
};
我们可以在sum实现中做dynamic_casts来单独处理每个案例,或者我们可以使用double dispatching。
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构造函数的所有其他类型,这是不可能的。