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.
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).