From: blurk on

I'm in a situation where I am defining a C++ API representing an
interface such that different applications can use the interface, yet
there can be different libraries that implement the interface. The goal
is for the applications to be able to be run against a test library
implementing the interface as well as the real implementation library
itself.

The way I have approached the API design is to specify a bunch of
abstract base classes, and obviously only the types of these base
classes are known to the API. The applications do not need to know
anything about the implementation classes (I am maybe somewhat
overzealous about that). For various reasons, I want to avoid the Pimpl
idiom (one target for the application is embedded environments, and I
don't want a bunch of delegating member functions or to fragment the
construction of the objects). Also, for any given implementation, most
of the abstract base classes will only have exactly one implementation
subclass.

I have come up with a way to implement getting a pointer or reference
of the derived class type from a pointer of the base class type without
using a dynamic_cast, and I'm curious about (a) whether this method can
be improved and (b) whether I'm seriously deluded about doing this (i.e.
am I taking my anti-cast stance too far). One "justification" I have
for avoiding dynamic_cast here is that my approach here has a stronger
guarantee than can be provided by dynamic_cast because dynamic_cast has
the possibility of returning a null pointer because the types do not
match up.

So here is the general outline of how I implement this:

Interface.h:

namespace Interface
{

// I use a base class using the curiously recurring template pattern
// because I need each abstract class to have a unique nested class
// providing an anonymous type that I can use in return values.
template <typename T>
class Base
{
public:
class I;
virtual I &Get() = 0;
virtual const I &Get() const = 0;
};


class Abstract : public Base<Abstract>
{
public:
virtual void Foo() const = 0;
};

} // namespace Interface


Implementation.h:

namespace Implementation
{
class Derived;
}

namespace Interface
{

template <>
class Base<Abstract>::I : public Abstract
{
public:
// Accessors returning nested type which is undefined to the
// interface, but visible to implementation
virtual I &Get() { return *this; }
virtual const I &Get() const { return *this; }

// Conversion operators to get to the actual implementation
// type.
virtual operator Implementation::Derived &() = 0;
virtual operator const Implementation::Derived &() const = 0;
};

} // namespace Interface


namespace Implementation
{

class Derived : public Interface::Base<Interface::Abstract>::I
{
public:
// Only here do we know the actual implementation type
virtual operator Derived &() { return *this; }
virtual operator const Derived &() const { return *this; }
virtual void Foo() const
{
std::cout << "Derived::Do" << std::endl;
}
void Impl() const
{
std::cout << "Derived::Impl" << std::endl;
}
};

} //namespace Implementation


Implementation.cpp:

int main(int argc, char *argv[])
{
Implementation::Derived d;
Interface::Abstract *ap = &d;
Implementation::Derived &rd = ap->Foo();
rd.Do();
rd.Impl();
const Interface::Abstract *cap = ap;
const Implementation::Derived &crd = cap->Foo();
crd.Do();
crd.Impl();
return 0;
}

--
Bernie
I do not want email replies, please followup to the group.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Sebastian Redl on
blurk wrote:

> I'm in a situation where I am defining a C++ API representing an
> interface such that different applications can use the interface, yet
> there can be different libraries that implement the interface. The goal
> is for the applications to be able to be run against a test library
> implementing the interface as well as the real implementation library
> itself.
>
> The way I have approached the API design is to specify a bunch of
> abstract base classes, and obviously only the types of these base
> classes are known to the API. The applications do not need to know
> anything about the implementation classes (I am maybe somewhat
> overzealous about that).

No, that's an extremely important design goal.

> I have come up with a way to implement getting a pointer or reference
> of the derived class type from a pointer of the base class type

What for? I thought the goal was the app not needing to know anything about
the library. Thus, the application has no need to get a pointer to the
derived class from the base class, ever. If it does, either your interface
or the app is broken.

> without using a dynamic_cast

The library, on the other hand, will need to get its own type from any base
type passed in. Now, you say that typically any interface will have just
one implementation class in a library. Then the method to get the derived
class is simple: use static_cast. There is no way the class could be
anything but what you expect. (OK, the application could try to mix
implementations, but it would be very stupid.) Static_cast in this case is
safe and sound.

If there are multiple derived classes, use dynamic_cast. That's what it's
for, after all. Better yet, don't cast at all - if there are multiple
implementations, chances are that the interface should be rich enough that
it suffices even for the library. Or that there is a common base of all
library classes that implement the interface that you can use with
static_cast.

> , and I'm curious about (a) whether this method can
> be improved

You could make it so that a reader would have even the faintest idea of
what's going on.

> and (b) whether I'm seriously deluded about doing this (i.e.
> am I taking my anti-cast stance too far).

Yes, you are.

> One "justification" I have
> for avoiding dynamic_cast here is that my approach here has a stronger
> guarantee than can be provided by dynamic_cast because dynamic_cast has
> the possibility of returning a null pointer because the types do not
> match up.

If you return a pointer in a situation where dynamic_cast returns null,
you've a bug, not a stronger guarantee.



--
Sebastian Redl

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: blurk on

Thanks for all the responses so far. I apologise for not checking the
actual code compiled before posting (I edited it down from a much bigger
test program, and really should have not rushed it so much). Also, as
is apparent from some of the responses, the example code is quite
unclear.


Martin Bonner wrote:
> Why does the CLIENT need to know about Derived?

Sebastian Redl:
>> I have come up with a way to implement getting a pointer or reference
>> of the derived class type from a pointer of the base class type
>
> What for? I thought the goal was the app not needing to know anything about
> the library. Thus, the application has no need to get a pointer to the
> derived class from the base class, ever. If it does, either your interface
> or the app is broken.

Of course you are both correct, and my example made it quite unclear
that I want the *implementation* to be able to get back the pointer /
reference to the implementation type when passed in a pointer of the
abstract base type. The whole point of the exercise of hiding the
implementation type is because it's none of the client's business.


int...(a)gmail.com wrote:

> First of all, you don't need dynamic_cast for all downcasts, only for
> virtual inheritance, or when you are not sure the cast will succeed.
>
> On the other hand, you can ensure that cast cannot fail by defining a
> private constructor in the interface, and specifying forward-declared
> implementation class as a friend class. That way, any valid non-null
> pointer to interface is guaranteed to point to an instance of
> implementation class (or some of its subclasses).

Aah, yes, in my actual interface I am already defining a protected
constructor (not private, I know, but at least no public). I just
wanted to avoid naming the implementation class (and, more specifically,
its namespace(s)) in the interface, and I wanted the implementation
class to strictly be a subclass, not a friend, to emphasis the is-a
relationship.


acehr...(a)gmail.com wrote:

> Since the visitor pattern is the answer to the problem in the subject
> line, and you don't mention it in your post, I don't know whether you
> tried but did not like the results. So, try the visitor pattern. :)

And now we get to the point where I don't post a corrected version of my
original code because, of course, this is the solution to my problem. I
had briefly looked at Alexandrescu's discussion of the visitor pattern
(rather than the canonical formulation), and with all the discussion of
visiting a hierarchy of polymorphic nodes in some container, I had
decided it didn't apply. But it does and looks like it works fairly
neatly, without me needed to expose implementation types in the
interface. (Well, except for the existence of visitor classes, but they
can remain somewhat anonymous.) So thank you for that hint, and making
me think harder. It was well worth the effort.

Cheers,

Bernie

--
I do not want email replies, please followup to the group.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]