** Is there a way (C++ syntax) to specify that a pointer should refer to
an object that derives from *two* specific classes?
eg, Suppose I have two classes, 'A' and 'B', and I want to specify that
pointer 'p' refers to an object derived from both. I *don't* want to
invent some class 'Bar' that derives from 'A' and 'B', and specify that
pointer 'p' should derive from that class 'Bar'.
Not easily. Note that Modern C++ Design by Andrei Alexandrescu would
be a good idea to buy. Good luck!
// your two base classes
class A
{};
class B
{};
// a good class
class C : public A, public B
{
};
// a bad class
class D
{};
// test whether T converts to U,
// that is, if T is derived from U
// taken from Modern C++ Design
//
template <class T, class U>
class Conversion
{
typedef char Small;
class Big {char dummy[2];};
static Small Test(U);
static Big Test(...);
static T MakeT();
public:
enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
};
// catches T == T
//
template <class T>
class Conversion<T, T>
{
public:
enum { exists = false };
};
// issues 'customizable' error
// this one is used for 'false' and has a default ctor
// adapted from MC++D
//
template <bool>
class Check
{
public:
Check() {}
};
// this one is used for 'true' and has a catch-all ctor
//
template <>
class Check<true>
{
public:
Check(...) {}
};
// your pointer class
// Base1 and Base2 are the two required base classes
// T is the pointer type
//
template <class Base1, class Base2, class T>
class MyPointer
{
T* t_;
class ERROR_must_inherit {};
public:
MyPointer(T *t)
{
// must name all the objects since the two statements will be taken
// as function declarations
ERROR_must_inherit the_error;
Check<Conversion<const T, const Base1>::exists > dummy1(the_error);
Check<Conversion<const T, const Base2>::exists > dummy2(the_error);
}
};
int main()
{
MyPointer<A, B, D> p(new D);
MyPointer<A, B, C> p(new C);
}
The first statement will give something like (well.. on Comeau)
line 77: error: no instance of constructor
"Check<<unnamed>>::Check [with <unnamed>=false]" matches the
argument list
The argument types that you used are:
(MyPointer<A, B, D>::ERROR_must_inherit)
Check<Conversion<const T, const Base1>::exists > dummy1(the_error);
^
detected during instantiation of
"MyPointer<Base1, Base2, T>::MyPointer(T *)
[with Base1=A, Base2=B, T=D]" at line 86
line 78: error: no instance of constructor
"Check<<unnamed>>::Check [with <unnamed>=false]" matches the
argument list
The argument types that you used are:
(MyPointer<A, B, D>::ERROR_must_inherit)
Check<Conversion<const T, const Base2>::exists > dummy2(the_error);
^
detected during instantiation of
"MyPointer<Base1, Base2, T>::MyPointer(T *)
[with Base1=A, Base2=B, T=D]" at line 86
Maybe someone has a better solution, or you could adapt this one to
your needs.
Jonathan