Можно написать оболочку, которая принимает любой тип, поддерживающий определенную операцию, например.Тип стирания для двоичных операций
#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-класса, который поддерживает сопзЬ-метод Foo, который можно назвать Жека в междунар, независимо, если это обычная функция член (как в классе А) или шаблон функции (как и в классе B) (и теперь игнорирует, что Гудини должен проявлять ценностную семантику). Пока что так хорошо, но я бы хотел написать оболочку, которая поддерживает двоичные операции, например. писать обертку, которая принимает любой тип, и вы можете, например, добавить любые две оболочек до тех пор, как может быть добавлена обернутая объекты и возвращает обернутый объект возврата от того:
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 + на двух развернутых объектах и снова обернуть результат, но я не могу понять, как это сделать.
Я бы сказал, что с помощью шаблонов и магии это можно решить, но я недостаточно умен, чтобы знать, как это сделать. –
Я думаю, вам может быть не повезло, учитывая ваше текущее описание. Определение того, какие возможные перегрузки для 'operator +' для использования потребует знания времени компиляции соответствующих типов, но вы специально удалили эту информацию о типе. Возможно, вы сможете сделать это для случаев, когда оба операнда должны быть одного типа. –