0

In my program (attempt to make a programming language), I have tokens. The tokens are represented with structs. My issue is that I don't know how to "evolve" the base token into a more complex token that can be returned into some type of collection with other derived/evolved tokens of different types.

Ex:

BaseToken -> VariableToken -> List of base tokens

BaseToken -> FunctionToken -> List of base tokens

Then when I iterate through the list, I can convert those base tokens back to their "evolved" token and continue the program.

My current attempt uses the structs BaseStruct,DerivedStruct & AnotherDerivedStruct. They are created as shared_ptrs.

#include<iostream>
#include<memory>


enum class Enums
{
 A,
 B,
 UNKNOWN,
};

struct BaseStruct
{
 Enums Type = Enums::UNKNOWN;
};

struct DerivedStruct : public BaseStruct
{
 int MoreData = 0;
};


struct AnotherDerivedStruct : public BaseStruct
{
 char different_Data;
};

I have to downcast this base struct to assign more values.

I cannot use static_pointer_cast directly since I need to first use make_shared<DerivedStruct>() or make_shared<AnotherDerivedStruct>() since the struct can be derived into different structs.

so

int main()
{
    auto BaseToken = std::make_shared<BaseStruct>();

    BaseToken->Type = Enums::B;
    
    bool ComplicatedLogicalLogic = false;
    
    if (ComplicatedLogicalLogic)
    {
     BaseToken = std::make_shared<DerivedStruct>();
     auto DerivedToken = std::static_pointer_cast<DerivedStruct> 
     (BaseToken);
     DerivedToken->Type; //this will be undefined
    }
    else
    {
     BaseToken = std::make_shared<AnotherDerivedStruct>();
     auto DerivedToken = std::static_pointer_cast<AnotherDerivedStruct> 
     (BaseToken);
     
     /// The value is reset so this condition is never met
     if (DerivedToken->Type == Enums::B)
     {
         std::cout << "IS B" << '\n';
     }
    
    }
}

I understand that using make_shared will wiped the existing data so I have to temporarily copy the original data, use make_shared and then reassign the data. This works for downcasting, but when this derived struct is added to a vector of type shared_ptr<BaseStruct>, there's no way of retrieving the derived data.

I want to know if there is any better way of storing "tokens" in which I can get all their derived data.

19
  • 1
    What you are doing in your revised post is discarding the original base object and reusing the pointer you had pointing to it to point to an entirely new, default initialized object. There is no carry over of values as you are tossing the old object entirely and starting fresh with a new one. Start by creating the derived object, work with it, if desired, via a pointer to base and, if desired even later, via a pointer to derived.
    – Avi Berger
    Commented Oct 29 at 3:04
  • 1
    To create it, you must know the specific derived type. You can't start with a base and later expand it. You can redirect the pointer to a different object later, but there will be no carry over of values unless you specifically copy/move over the values as it is a different, independent object.
    – Avi Berger
    Commented Oct 29 at 3:15
  • 2
    A family of types is not a single type. A base class will not transform into a derived class no matter how you ask it. When you create a base class, you don't have a derived class. You can either copy the values you want over or you can wait until you know what derived class you want before creating an object.
    – Passer By
    Commented Oct 29 at 3:22
  • 1
    This question is a difficult read. After re-reading it a few times, I think I understand what you might be trying to say, but a Stack Overflow question should not be that hard to understand. One good example might be "I have to downcast this base struct to assign more values." This basically assumes that the reader knows what your goal is (which is a bad assumption), focusing instead on how you're getting to that goal. At a guess, this one sentence should be expanded into a full paragraph that explains what's going on. I'd also put it before the code (cf. How to Ask).
    – JaMiT
    Commented Oct 29 at 4:41
  • 1
    "I have my base struct that contains values as a shared_ptr" -- This does not match your code. I read this as saying you have a base struct, let's call it BaseStruct, that has a shared_ptr member to the values it contains. Your code indicates that instead you have a shared_ptr to the base struct. This would be "I have a shared_ptr to my base struct that contains values". And "values" reads strange. Not exactly wrong, but try "fields" or "data members" or "some data".
    – JaMiT
    Commented Oct 29 at 4:45

1 Answer 1

0

You want to create a base class object, play around with it, then promote it to a derived class object. C++ doesn't have this object promotion feature (some other languages do).

What you probably need is create the derived object directly, without creating an intermediate base class object first. Such an object has no legitimate uses of its own, in your example at least. The base class can and should be made abstract to protect from erroneous instantiation.

If for some reason you do need to make BaseStruct instantiatable, extract data to a separate class hierarchy and have BaseStruct contain a pointer to a data object (you won't have DerivedStruct, just DerivedData).

7
  • Since there are multiple "derived" structs, would the member for the BaseStruct that points to the "derived" struct has to be a template since the BaseStruct has to be able to point to different structs i.e BaseStruct -> StructA, BaseStruct -> StructB ?
    – galaxied
    Commented Oct 29 at 21:07
  • No, you need a new base class for the data to derive from. So you have struct StructA : BaseData {...} etc. Commented Oct 29 at 22:14
  • Isn’t that what is in the example? Struct derivedStruct : public BaseStruct
    – galaxied
    Commented Oct 29 at 22:16
  • "Isn’t that what is in the example?" No. Your example has one level of indirection less. Anyway, don't do that. Just make BaseStruct abstract. That's all you need. Commented Oct 29 at 22:23
  • So there is a virtual deconstructor?
    – galaxied
    Commented Oct 29 at 22:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.