Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: What type to set if I want to return SFML drawable objects?  (Read 948 times)

0 Members and 1 Guest are viewing this topic.

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
What type to set if I want to return SFML drawable objects?
« on: August 27, 2023, 07:15:56 pm »
Hello everyone!  :) I have a question. I'm new to C++ and SFML. How can I return any drawable object in one type? i.e:
// what type?
sfml_drawable? function(int x) {
    if(x == 1) {
        sf::RectangleShape rect(some_args);

        return rect;
    } else if(x == 2) {
        sf::CircleShape circl(some_args);

        return circl;
    }
}

function(1) // => sf::RectangleShape
function(2) // => sf::CircleShape
 

Please help me :P
« Last Edit: August 27, 2023, 07:22:47 pm by sfmluser1 »

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #1 on: August 27, 2023, 08:14:13 pm »
Hi!
And welcome!

It is possible using casting but it's clunky and very easy to cause errors if it's not perfectly designed.

I suppose the question that should be asked here is: why do you need to do that?

That is, there may be a better, simpler and more safe way of doing it.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #2 on: August 27, 2023, 08:51:39 pm »
Basically I have function that generates SFML object from LevelObject (template). i.e
void draw(LevelObject obj, sf::RenderWindow &window) {
    if(obj.type == RECTANGLE) {
         sf::RectangleShape rect(obj.width, obj.height);

        window.draw(rect);
    } // other types
}
 

So now I'd like to return generated sfml object, for future export object properties to file, and later load them. Also later I'd like to create vector that will contain all loaded objects from file, but the same problem remains. What vector type should I have? I tried std::variant:
using ExportableSFMLObject = std::variant<sf::RectangleShape, sf::CircleShape, sf::Text, sf::Sprite, int>;

ExportableSFMLObject function(...) { ... }
 

But then I couldn't figure out exactly what type function returns, maybe it's RectangleShape, or sf::CircleShape. Even if I could resolve what type function returns, function GetType, where'd I'd like to realize type resolving, is also doesn't have exact type to return.

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #3 on: August 27, 2023, 08:53:28 pm »
It's the main problem in my project

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #4 on: August 27, 2023, 09:08:52 pm »
I was thinking about a union, although I'd probably use a union of pointers, so I can understand why you' ve chosen std::variant.

It turns out that you can check a variant's type (from it's "alternatives" that you have provided) by getting the index of the alternative:
https://en.cppreference.com/w/cpp/utility/variant/index

So, it'd be something like:
switch (ExportableSFMLObject.index())
{
    case 0u:
        // it is an sf::RectangleShape
    break;
    case 1u:
        // it is an sf::CircleShape
    break;
    case 2u:
        // it is an sf::Text
    break;
    case 3u:
        // it is an sf::Sprite
    break;
    case 4u:
        // it is an int
    break;
}

Or, indeed, maybe this:
if (std::holds_alternative<sf::RectangleShape>(ExportableSFMLObject))
    ; // it is an sf::RectangleShape
else if (std::holds_alternative<sf::CircleShape>(ExportableSFMLObject))
    ; // it is an sf::CircleShape
else if (std::holds_alternative<sf::Text>(ExportableSFMLObject))
    ; // it is an sf::Text
else if (std::holds_alternative<sf::Sprite>(ExportableSFMLObject))
    ; // it is an sf::Sprite
else if (std::holds_alternative<int>(ExportableSFMLObject))
    ; // it is an sf::int


It's worth noting that I've not test this.
« Last Edit: August 27, 2023, 09:12:05 pm by Hapax »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #5 on: August 27, 2023, 09:16:33 pm »
I think its going to work! But is it possible to contain type resolving code in function? Or like I said it's impossible because there is no exact type?

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #6 on: August 27, 2023, 09:28:50 pm »
What exactly do you want the function to return?

If it's LevelObject::obj, you can set it from the index using similar code to above.

e.g.
LevelObject::type getLevelObjectType(ExportableSFMLObject& xObj) const
{
    switch(xObj.index())
    {
        case 0u:
            return RECTANGLE;
        case 1u:
            return CIRCLE;
        case 2u:
            return TEXT;
        case 3u:
            return SPRITE;
        case 4u:
            return INT;
    }
}
...or whatever you named them ;D
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #7 on: August 27, 2023, 09:40:21 pm »
I mean getType function should return SFML drawable class:
??? getType(ExportableSFMLObject obj) {
    if (std::holds_alternative<sf::RectangleShape>(obj))
        ; // it is an sf::RectangleShape
        // return sf::RectangleShape
    else if (std::holds_alternative<sf::CircleShape>(obj))
        ; // it is an sf::CircleShape
        // return sf::CircleShape
    else if (std::holds_alternative<sf::Text>(obj))
        ; // it is an sf::Text
        // etc
    else if (std::holds_alternative<sf::Sprite>(obj))
        ; // it is an sf::Sprite
    else if (std::holds_alternative<int>(obj))
        ; // it is an sf::int
}
 
« Last Edit: August 27, 2023, 09:49:55 pm by sfmluser1 »

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #8 on: August 27, 2023, 09:51:31 pm »
So not the type but the object itself?

Then you'll likely need function overloading or templates.

Saying that, why do you need to do that if the variant already holds the object and you can just use the index (or my function) to know which type.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #9 on: August 27, 2023, 10:16:33 pm »
I'm very sorry I know what is a template or method overloading, but I don't know how to implement this. It would been easier if std::variant<v1, v2> returned exactly v1 or v2, not std::variant. So for example how do I implement method overloading if I have only one type? (ExportedSFMLObject). I'm sorry I don't understand

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #10 on: August 28, 2023, 12:07:56 pm »
Well, the problem you have is that you can't return one item or the other, you can return a variant that contains one or the other; that seems to be what it's for.

Function-wise, the simplest solution would just be to be more explicit.
switch(xObj.index()) // as above
{
    case 0u:
        doStuffWithRectangleShape(xObj);
    // etc.
}
but overloading could look like this:
doStuffWithXObj(xObj.get());
where it would call whichever function is required for the type:
void doStuffWithXObj(sf::RectangleShape& rectangleShape);
void doStuffWithXObj(sf::CircleShape& circleShape);
// etc.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

sfmluser1

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: What type to set if I want to return SFML drawable objects?
« Reply #11 on: August 28, 2023, 03:06:53 pm »
I'm going to completely rethink some feature implementations because I don't think I can fix this bug. Thank you for helping, I very appreciate it!

Hapax

  • Hero Member
  • *****
  • Posts: 3366
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: What type to set if I want to return SFML drawable objects?
« Reply #12 on: August 28, 2023, 10:11:42 pm »
It's likely you should rethink the design so this isn't necessary.
If you have a function that is returning an unknown object, what are you doing with that object where you don't need to then know what the type is before you use it?

But...

If you absolutely must return an unknown drawable, you can cast.
Warning! This is 'dangerous' and my example is likely to not be fully safe.

Note that this is only really useful if you actually don't need to know its type (and only using base class stuff)

sf::Drawable* makeThing(const std::size_t whichThing)
{
    switch (whichThing)
    {
        case 0u:
            sf::Rectangle rectangle;
            return dynamic_cast<sf::Drawable*>(&rectangle);
        break;
        case 1u:
            sf::CircleShape circle;
            return dynamic_cast<sf::Drawable*>(&circle);
        break;
    }
}

sf::Drawable* thing1{ makeThing(0u) };
window.draw(*thing1); // a rectangle
sf::Drawable* thing2{ makeThing(1u) };
window.draw(*thing2); // a circle

Or something...
But you'd still need to know which thing it is if you need to do specific things (e.g. if you need to set the circle's radius).
And you'd need to cast it back.


Not certain if this code is sound either so I take no responsibility in any issues causes by using it 8)
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

 

anything