3

I have a base class and I want to store instances of its derivatives in a collection of some sort.

At first I created a map:

 std::map<int, Variable> varriableItems;

and then ussing templates I created functions for each derivative and I tried passing in the derivatives like so:

template <>
void Array::addToMap<Number>(Number input)
{
numberVariables[itemCount_] = input;    
itemCount_++;
}     

By doing so this function was not called because everything was of type Variable of course and I found out about slicing.

So instead I changed my map to take in pointers to my base class

  std::map<int, Variable*> varriableItems;

but the problem I have is that all my objects are not created as pointers so I could not pass them in and I was getting errors. No suitable conversion from "Number" to "Variable" exists.

Due to my implementation I can only create instances of objects like so:

auto aNumberVariable = Number{50};

Ofcourse if I instead do:

Number aNumberVariable = new Number(50);

it works great.

The reason am doing this is explained bellow.

Please bear with me because this is a weird assignment.

We were asked to create a program that behaves/understands the syntax of a programming language called Logo, without actually analyzing the text as an input file, but rather "disguise" it to appear as such while in fact we just use C++ using what we learned from C++ and lots of overloads and pre-processor tricks

We have to be able to make our own "types" of variables called NUMBER,WORD,BOOLEAN,ARRAY, LIST,SENTENCE.

To declare them we have to use(note no semi-colons should be used):

//define number variable with value 21
MAKE number = NUMBER: 21
//define hello variable with value “hello”
MAKE hello = WORD: “hello”
//define myMoves variable contains list of turtle moves
MAKE myMoves = LIST [
    LIST [WORD: “FORWARD”, NUMBER: 100],
    LIST [WORD: “LEFT”, NUMBER: 90],
    LIST [WORD: “FORWARD”, NUMBER: 100]
]
//define array variable with empty array
MAKE array = ARRAY {
    number,
    hello,
    NUMBER: 12
    BOOLEAN: TRUE,
    ARRAY {
        myMoves,
        LIST [WORD: “BACK”, NUMBER: 100]
    }
}
//define book variable with sentence type
MAKE book = SENTENCE (hello, WORD: “hello!”)

That's just a small part, we later have to support functions, nested loops , etc. So do this I have to find a way to use the colon since I cannot overload it, so I did this:

//Create an instance of Number and write the first half of the ternary operator so we 
//always get the false value so we can use the : like this
#define NUMBER  Number{} = (false) ? 0 
//semicolon infront for the previous command that needs it
#define MAKE ;auto

So now this:

//following commands will deal with the semicolon
MAKE myNumber = NUMBER: 21

worked great and it actually gets replaced by the processor to this:

auto myNumber = Number{} = (false) ? 0 : 21

So i worked with this for all my derivatives and I proceeded to overload operators to compare them, implement if else function in a similarly weird syntax.

Now I either have to figure out a way to make this work again but this time creating them as pointer instead (Which I assume is the only way for this to work, but I so far I couldn't figure it out) or create a single class for all types but doing it in separate objects that all inherit from a single base class makes more sense to me.

And am not sure how strict they will be, it is an unconventional project assignment for sure.

The reason I want to hold them together in a container is so I can then implement an Array and list object that can hold every type. At first I tried to use a different container for each type and made an iterator to iterate multiple maps separately, but when I got to the LIST implementation things got weird.

The list syntax is using the brackets [ ] which can only get 1 input value, so the idea was to collect them by overloading the comma operator and pass in one value to the list object.

I know this is weird , thank you for your time

Stavros Argyrou
  • 305
  • 1
  • 2
  • 9

1 Answers1

3

I didn't read through all of your post. (actually I did because your task is so ... beyond words) but if you need polymorphism in a container and you also need the container to hold the objects, then the solution is unique_ptr:

container<std::unique_ptr<Base>>

In your case it would go something along this:

std::unordered_map<int, std::unique_ptr<Variable>> varriableItems;

varriableItems[0] = std::make_unique<Number>(50);
bolov
  • 72,283
  • 15
  • 145
  • 224
  • This worked! I looked it up a bit and I just used shared_ptr , seemed a better fit for my needs. Thank you so much, have a great day. – Stavros Argyrou Jan 12 '18 at 17:56