3

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++ ?

3
  • What is the type that could be passed to this constructor, and how is this type defined? Commented May 3, 2019 at 15:59
  • Make it a template and restrict it with std::enable_if and std::is_base_of. Commented May 3, 2019 at 16:00
  • @dbush examples are: class Sprite : public Drawable, public Transformable or class Text : public Drawable, public Transformable (but it can be anything which is derived from Drawable and Transformable) Commented May 3, 2019 at 16:02

2 Answers 2

4

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) {}
};
Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.