特定の操作をサポートする任意のタイプを取るラッパーを作成することができます。
#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);
}
通常のメンバー関数 (クラス A など) であるか関数テンプレート (クラス B など) であるかに関係なく、int で呼び出すことができる const メソッド foo をサポートする Houdini クラスで何でもラップできます (そしてHoudini が値のセマティクスを表示する必要があることは今は無視してください)。ここまではうまくいきましたが、私がやりたいことは、バイナリ操作をサポートするラッパーを作成することです。たとえば、任意の型を受け入れるラッパーを作成し、ラップされたオブジェクトを追加できる限り、任意の 2 つのラッパーを追加できます。追加からラップされた戻りオブジェクトを返します。
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
}
保存するタイプが事前にわかっている場合は、訪問者を書き込むことでそれを行うことができますが、それはまさに私がやりたくないことです。両方のオブジェクトをアンラップし、ラップされていない 2 つのオブジェクトで operator+ を呼び出して、結果を再度ラップする必要がありますが、その方法がわかりません。