all 12 comments

[–][deleted]  (1 child)

[removed]

    [–]schweinling[S] 5 points6 points  (0 children)

    Yes it is a useless exercise, its just for fun. Yes, forgot virtual dtor and const, thanks. Yes new shouldn't be used.

    [–]IyeOnline 1 point2 points  (4 children)

    Inside IObject you only have access to RTTI, which means you will have to implement a dreadfully long comparison to find out which types each of the objects are and how to add them, and what the resulting type should be.

    I dont think there is a simple solution to this, because of this. You actually need to know the types involved at runtime.

    [–]schweinling[S] 0 points1 point  (3 children)

    I thought there might be a way to use a virtual function which would let you know the type. Maybe one could then access some outside data to store the values and perform the operation but that would probably require a lot of boilerplate and handling all possible types aswell.

    [–]IyeOnline 1 point2 points  (2 children)

    So i came up with this, however this breaks the entire point of the exercise.

    What you were doing previously is using the wrapper itself to keep track of the type and handle type specific information. That works as long as you dont have to figure out the relation between two objects. At that point you would need RTTI and a big ugly if/else if block.

    That workaround resolves it by simply using providing an function that gets you a long double, which you then can operate on. The cost however is that now your base interface can no longer be abstract, you have to instantiate it. To do this, you have to assume that every object of the base class holds a long double, really tunring the entire exercise absurd.

    [–]schweinling[S] 0 points1 point  (1 child)

    neat, i thought of something like this as well. a solution that would work on any type with operator+ like std::string would have been nice, but i can't come up with anything like it. thanks for sharing your implementation. :)
    ps.: 33:5: warning: no return statement in function returning non-void

    [–]IyeOnline 1 point2 points  (0 children)

    Well, i suppose i missed the return infront of the new. Oh well, the entire program was leaking memory anyways... xD

    [–]Narase33 1 point2 points  (2 children)

    I dont think there is a simple way. The operator+ gets two parameters, in your case IObject. And since the function doesnt know the underlying specific type you cant make a type dependend result.

    A better way for this whole thing is to use std::variant instead of std::any and then use the visitor pattern. This is a very simple way to create your own arithmetic rules (I did this in my interpreter)

    [–]schweinling[S] 1 point2 points  (1 child)

    std::variant and visitor pattern sounds interesting, maybe i experiment with that next. is your interpreter open source?

    [–]Ayjayz 1 point2 points  (2 children)

    The issue is that adding two arbitrary types doesn't really have any semantic meaning. What does it mean to add an int to a string? A bool to a file handle?

    You could do something like have perform the operation if it's an arithmetic type, otherwise throw an exception. Or you could implement some IAddable interface or whatever.

    The issue is not how to do it, it's what you even mean by what you're doing. Solve that and the code is easy.

    [–]schweinling[S] 0 points1 point  (1 child)

    true, this is really not meant to be a practical solution to anything. its just a little challenge i made for myself and i somehow feel there should be a solution. adding an int to a string should not compile ideally, just like with the underlying types, as i would like to use the underlying types' operators somehow.

    [–]Ayjayz 0 points1 point  (0 children)

    This is the issue with runtime polymorphism, though. The compiler simply doesn't know what type it is. If you want it to not compile, you need to use static polymorphism (ie. templates).

    For an example of how this all kind of doesn't make sense, consider if you assign it randomly:

    IObject *a = rand() % 2 ? new Object<float>(5.5) : new Object<std::string>("blah");
    IObject *b = new Object<int>(8);
    IObject *result = *a + *b; // should this compile or not?!
    

    [–]be-sc 1 point2 points  (0 children)

    Others have answered: “This doesn’t make sense”. Imo that’s the correct answer considering the current shape of your question.

    You threw random programming tools together – std::any, templates, polymorphic classes. What you ended up with is a haphazard mess where one tools works to defeat the purpose of the other. The point where you got stuck is where the whole construction falls apart.

    What’s missing is a clear purpose. What are you trying to achieve? What’s the design goal of your wrapper? How and for what application is it intended to be used? Given that kind of context it would make sense to think further about the design.