C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::chimeric_ptr -- it's alive... it's ALIVE!

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Thu, 27 Nov 2025 11:46:05 +0000
On Thu, Nov 27, 2025 at 4:32 AM Thiago Macieira wrote:
>
> This is not a different problem. It's the same problem, based on the same
> poorly-defined API. Why did someone need a base for each and every one of the
> operations? Are they used in multiple places? Is there at least one class that
> has one but not the rest of the bases? This seems to me that someone used a
> C++ feature because they could, not because they needed it or because it was
> good design.


I don't work on the microscopes anymore but I can remember a lot of
the code. I've changed a few names in the following code so as to
avoid sharing secrets.

The desktop PC software development kit (i.e. SDK) exposed a function
that returned a pointer to an interface for a microscope, let's say:

    IMicroscope ConnectMicroscope( int model );

You could pass it 1 for the Yellow microscope, 2 for the Green
microscope, 3 for the Orange microscope and so on. Some microscope
models only had the most basic features. Some had many many features.
This SDK was developed over about 25 - 30 years through the life
cycles of about half a dozen microscopes, and it became massive.

The most feature-rich microscope was the Pink microscope. The class
that managed it was defined something like:

    class Pink : public IMicroscope, public IUtility, public IDrift,
public IIllumination, public IStage, public IEscape, public
IObjective, public IDiagnostics, public IIris, public IPower, public
IAsyncControl, public ICommsHandler {
        . . .
    };

Each of those 12 base classes had maybe 6 - 10 virtual methods,
thereabouts. The more basic microscopes only inherited from about 4 or
5 base classes. For example the base class 'IStage' might have been
something like:

    class IStage {
    public:
        virtual void SetSpeed( float ) = 0;

        virtual float GetSpeed(void) = 0;
        virtual float GetSpeedMin(void) = 0;
        virtual float GetSpeedMax(void) = 0;
    };

So these base classes weren't trivial. In fact the one that managed
the objectives I think had two or three dozen methods.

Now let's say I was to come along at a later stage, with the goal of
writing a function that could safely prepare a microscope to be
powered down and packaged for shipping. So in this function, I would
move the stages to a safe place, I would cut the power circuit to the
lights and motors (but not before cooling down the lightbulbs), I
would reset the diagnostics, and so on. So I might write a function
something like:

    void PrepareForShipping( std::chimeric_ptr< IStage, IPower,
IIllumination, IDiagnostics, ICommsHandler > );

So I think the question to be answered here is as follows. Which of
the following is true, A or B?
    (a) I have used 'chimeric_ptr' to compensate for a bad design of
class hierarchy
    (b) The class hierarchy is designed okay, and 'chimeric_ptr' is a
new feature that makes it easier to deal with objects that are
required to have two or more specific base classes

I'm genuinely interested to hear opinions on this. I think it's a case
of B, because I don't see anything wrong with the class hierarchy. Yes
the hierarchy is complex, but that's because that problem being solved
is complex. What I'm saying is that I don't think the class hierarchy
is more complex that it needs to be.

Received on 2025-11-27 11:46:17