What you can do is create a class with a templated constructor that accepts an arbitrary pointer, uses implicit downcasting to get the two interfaces you want, and then implements the combined interface.
struct IFoo
{
virtual void foo() = 0;
};
struct IBar
{
virtual void bar() = 0;
};
struct IFooAndBar : public IFoo, public IBar {};
class FooAndBarCompositor : public IFooAndBar
{
public:
template <class T>
FooAndBarCompositor(T* pImpl) : m_pFoo(pImpl), m_pBar(pImpl) {}
void foo() {m_pFoo->foo();}
void bar() {m_pBar->bar();}
private:
IFoo* m_pFoo;
IBar* m_pBar;
};
Then you write a function that accepts IFooAndBar* if both interfaces are required, and the caller can construct a FooAndBarCompositor on the stack that dispatches to the object of their choice. It looks like:
void testFooAndBar(IFooAndBar* pI) {}
void baz(Fred* pFred)
{
FooAndBarCompositor fb(pFred);
testFooAndBar(&fb);
}
This is not very general, and forces you to write dispatch functions in the compositor. Another approach is to have a generic interface compositor template:
template <class IA, class IB>
class InterfaceCompositor
{
public:
template <class T>
InterfaceCompositor(T* pObj) : m_pIA(pObj), m_pIB(pObj) {}
IA* AsA() const {return m_pIA;}
operator IA* () const {return AsA();}
IB* AsB() cosnt {return m_pIB;}
operator IB* () const {return AsB();}
private:
IA* m_pIA;
IB* m_pIB;
};
Then the function looks like:
void testFooAndBar(InterfaceCompositor<IFoo, IBar> pI)
{
IFoo* pFoo = pI; // Or pI.AsA();
IBar* pBar = pI; // Of pI.AsB();
}
This requires the function that wants to enforce the multiple interfaces to either use the compositor where an A* or B* is expected (e.g. assignment or function parameter) or explicitly call the appropriate AsX() method. Specifically, the interface to use cannot be inferred from the use of the -> operator and the * operator has no meaning on the composite.
If you go with the generic code, you can use the same template for enforcing that the object support both IBar and IBaz as well.
C++0x will introduce variadic templates that will allow this concept to be extended to arbitrary numbers of interface classes.