Interfaces and functions...

  • Thread starter =?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=
  • Start date
?

=?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=

Lets say we have some interfaces declared:

class A { virtual void a() = 0; };
class B { virtual void b() = 0; };
class C { virtual void c() = 0; };

We also have some classes implementing none or some of these
interfaces. Now I think it would be neat if I could define a function
that will accept an object that implemts both interface A and B as
input. Something like this:

void AcceptAAndB(/* parameter type */);

This funtion should accept the following classes:

class AB : public A, public B { };
class ABC : public A, public B, public C { };

The function should not accepts arguments of the following classes:

class JustA : public A { };
class JustB : public B { };

As far as I can see there is no easy way of doing this in C++. But I
would really like to be able to do it. =)

Has anyone around here been trying to do something like this? Any
ideas or thoughts along these lines?

Regards,
Mattias
 
J

John Harrison

Mattias Brändström said:
Lets say we have some interfaces declared:

class A { virtual void a() = 0; };
class B { virtual void b() = 0; };
class C { virtual void c() = 0; };

We also have some classes implementing none or some of these
interfaces. Now I think it would be neat if I could define a function
that will accept an object that implemts both interface A and B as
input. Something like this:

void AcceptAAndB(/* parameter type */);

This funtion should accept the following classes:

class AB : public A, public B { };
class ABC : public A, public B, public C { };

The function should not accepts arguments of the following classes:

class JustA : public A { };
class JustB : public B { };

As far as I can see there is no easy way of doing this in C++. But I
would really like to be able to do it. =)

Has anyone around here been trying to do something like this? Any
ideas or thoughts along these lines?

Regards,
Mattias

I think you should consider generic programming instead of object orientated
programming

template <class T>
void AcceptAAndB(T& t)
{
t.a();
t.b();
}

This will fail to compile if type T (whatever it is) does not have zero
argument methods called a and b.

john
 
V

Victor Bazarov

Mattias said:
Lets say we have some interfaces declared:

class A { virtual void a() = 0; };
class B { virtual void b() = 0; };
class C { virtual void c() = 0; };

We also have some classes implementing none or some of these
interfaces. Now I think it would be neat if I could define a function
that will accept an object that implemts both interface A and B as
input. Something like this:

void AcceptAAndB(/* parameter type */);

This funtion should accept the following classes:

class AB : public A, public B { };
class ABC : public A, public B, public C { };

The function should not accepts arguments of the following classes:

class JustA : public A { };
class JustB : public B { };

As far as I can see there is no easy way of doing this in C++. But I
would really like to be able to do it. =)

Has anyone around here been trying to do something like this? Any
ideas or thoughts along these lines?

Here is an idea: KISS ['keep it simple, silly']. Accepting interfaces
is pointless unless you use the functions they implement. So, if you
simply define the 'AcceptAAndB' as a template that uses both 'a' and 'b'
functions, you've achieved the goal, as far as C++ is concerned:

template<class Interface> void AcceptAAndB(Interface& ab) {
...
ab.a();
...
ab.b();
}

because a class that doesn't implement both 'a' and 'b' will be rejected
at compile-time. (Of course this presumes 'a' and 'b' are callable,
unlike in your example, where they are private)

Some will argue that there can exist another class

class Implements_a_and_b_not_related_to_A_or_B {
public:
int a();
double b();
};

which the function would happily accept, but this is where you have to
decide whether you need the run-time polymorphism or just compile-time
one.

Another way of doing that is, of course, to introduce a class AB:

class AB : public A, public B {
public:
void a() = 0;
void b() = 0;
};

from which all other classes should derive to be "accepted":

void AcceptAAndB(AB& ab) {
...
}

.. There are probably some template tricks you can play to limit the set
of types a template function can accept. Something like "isBaseOrDerived"
or something in that area. They are neat tricks and demonstrate the power
of C++ generic programming abilities, but I am still to encounter real-
life need for those (not to say that there isn't any).

V
 
T

Tom Widmer

Lets say we have some interfaces declared:

class A { virtual void a() = 0; };
class B { virtual void b() = 0; };
class C { virtual void c() = 0; };

We also have some classes implementing none or some of these
interfaces. Now I think it would be neat if I could define a function
that will accept an object that implemts both interface A and B as
input. Something like this:

void AcceptAAndB(/* parameter type */);

This funtion should accept the following classes:

class AB : public A, public B { };
class ABC : public A, public B, public C { };

The function should not accepts arguments of the following classes:

class JustA : public A { };
class JustB : public B { };

As far as I can see there is no easy way of doing this in C++. But I
would really like to be able to do it. =)

Has anyone around here been trying to do something like this? Any
ideas or thoughts along these lines?

You can do something like this:

#include "boost/mpl/and.hpp"
#include "boost/type_traits.hpp"
#include "boost/enable_if.hpp"

void AcceptAAndBImpl(A& viewAsA, B& viewAsB); //implement in .cpp file

using namespace boost;

template <class T>
enable_if<
mpl::and_<
is_base_and_derived said:
void>::type AcceptAAndB(T& t)
{
AcceptAAndBImpl(t, t); //should always compile without error
}

Apologies for any errors. The above should interact fine with
overloading. See enable_if, mpl and type_traits libraries at
www.boost.org. Obviously, the AcceptAAndBImpl bit is just there to
allow you to implement the function in a .cpp file by putting the
implementation in a non-template function.

Tom
 
J

Jesper Madsen

I will just supply another possibility (or maybe mine is overlapping some of
the others..)

Inherit from the InterfaceSupplier and "ask it" what interfaces it
implements, via the getInterface functions...

class A;
class B;
class C;
class InterfaceSupplier {
public:
virtual A* getInterfaceA(){ return 0; };
virtual B* getInterfaceB(){ return 0; };
virtual C* getInterfaceC(){ return 0; };
virtual ~InterfaceSupplier();
};

class A {
public:
virtual void a()=0;
};

class B {
public:
virtual void b()=0;
};

class ConcreteA : public A {
public:
virtual void a(){};
};

class ConcreteB : public B {
public:
virtual void b(){};
};

The one i would prefer...

class AB : public InterfaceSupplier {
public:
virtual A* getInterfaceA(){ return &a_; };
virtual B* getInterfaceB(){ return &b_; };
private:
ConcreteA a_;
ConcreteB b_;
};

OR...

class AB : public InterfaceSupplier,class A,class B {
public:
virtual A* getInterfaceA(){ return this; };
virtual B* getInterfaceB(){ return this; };
virtual void a(){};
virtual void b(){};
};

Jesper
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top