Ekz
Ekz

Reputation: 71

Function argument inheriting two types simultaneously

I'm trying to make a constructor in C++ (C++17 is fine), which has one argument, and I want this argument to be inherited from two types.

So I have this struct:

struct SceneNodeData {
    Drawable* drawable;
    Transformable* transformable;

    SceneNodeData(
        Drawable* drawable,
        Transformable* transformable
    ) : drawable(drawable), transformable(transformable) {}
};

But for convenience I want another constructor, with only one parameter, which is Drawable and Transformable at the same time (like Sprite):

struct SceneNodeData {
    Drawable* drawable;
    Transformable* transformable;

    SceneNodeData(
        <Drawable, Transformable>* drawableAndTransformable
    ) : drawable(drawableAndTransformable), transformable(drawableAndTransformable) {}
};

Is there any way to do this in C++ ?

Upvotes: 3

Views: 70

Answers (2)

NathanOliver
NathanOliver

Reputation: 180500

You can use a template and constarin the type using the type trait std::is_convertible to check if the type provided can be cast to both types. That would look like

struct SceneNodeData {
    Drawable* drawable;
    Transformable* transformable;

    template<typename T, std::enable_if_t<std::is_convertible_v<T*, Drawable*> &&
                                          std::is_convertible_v<T*, Transformable*>, bool> = true>
    SceneNodeData(T* drawableAndTransformable) : drawable(drawableAndTransformable), transformable(drawableAndTransformable) {}
};

Upvotes: 4

Brian Bi
Brian Bi

Reputation: 119144

Not quite, but:

  • You could define a class DrawableTransformable publicly derived from both Drawable and Transformable, and have your constructor take an argument of type DrawableTransformable*. Any concrete class derived from DrawableTransformable would need to implement the pure virtual functions from both Drawable and Transformable.
  • You could define a constructor template taking T* with an SFINAE check that T is publicly derived from both Drawable and Transformable. Or you could omit the SFINAE check and simply let a hard error occur in the initialization of drawable and transformable.

Upvotes: 3

Related Questions