0

I have to have a semantic stack in my project which is going to hold multiple types in it.
I aim to have my project to use modern C++.
What is the correct way to have a stack of any type ?
Equivalent version in java is Stack<Object>.
Which of these are correct?

  1. Use void* and cast it to the type I want.
  2. Something as 1 but using some smart pointers. (I don't know what)
Parsa Noori
  • 198
  • 1
  • 1
  • 10
  • 1
    What do you mean by "correct"? – Scott Hunter Feb 03 '22 at 01:52
  • What best practice is. What modern alternative c++ has implemented. – Parsa Noori Feb 03 '22 at 01:53
  • Possible Dupe: [Vector that can have 3 different data types C++](https://stackoverflow.com/a/26208947) – SuperStormer Feb 03 '22 at 01:55
  • I cannot predict the value types. I don't know even if they are finite. – Parsa Noori Feb 03 '22 at 01:56
  • 4
    @ParsaNoori If you don't know the types, then you will not be able to use the elements even if you manage to put them into the container. This sounds like a XY problem. C++ is not Java and it is not a good idea to translate concepts from Java to C++. – user17732522 Feb 03 '22 at 01:59
  • It's not working yet, since I haven't implement it yet. I'm sure `void*` is a solution but I don't think its a good, modern one. @user17732522 – Parsa Noori Feb 03 '22 at 01:59
  • 2
    @ParsaNoori `void*` wont work either if you can't predict the types in advance. – user17732522 Feb 03 '22 at 02:00
  • I suggest you present an example for your use case. You are probably going about this the wrong way. – user17732522 Feb 03 '22 at 02:01
  • @user17732522 It is predictable of course, but it's nasty. It's e huge project and I don't think a pair of enum and variant pair is a good choice since it needs updating each time a new type is going to be used. – Parsa Noori Feb 03 '22 at 02:02
  • 1
    If the data type to be stored truly has no bounds you probably have a design problem and should step back and figure out how you got into this mess rather than trying to bull your way through. The best practice for this use case is going to be "Don't Do It!" – user4581301 Feb 03 '22 at 02:02
  • @ParsaNoori It doesn't need to be a variant. A shared base class is also a possibility. But in either case the types must be limited to some subset of all types. – user17732522 Feb 03 '22 at 02:03
  • @user17732522 it's correct, but what can I do when I have primitive types there too ? – Parsa Noori Feb 03 '22 at 02:04
  • 2
    And if you Absolutely Have To Do It! convert all possible types into a generic form, like a serialized string, and store that generic type. – user4581301 Feb 03 '22 at 02:05
  • @user4581301 I guess that's a good idea! – Parsa Noori Feb 03 '22 at 02:06
  • There is also [`std::any`](https://en.cppreference.com/w/cpp/utility/any), but using it requires you to know what you actually stored so you can safely get it back out again. – user4581301 Feb 03 '22 at 02:08
  • @user4581301 Post your solutions in answers so I can select both of them as the correct answer, if you want to. – Parsa Noori Feb 03 '22 at 02:10
  • Can you provide code that shows how you are planning on retrieving the element's by known types? – Galik Feb 03 '22 at 07:05
  • @Galik it's a compiler project. In the parser I know which value has come up by the name of the non terminal and hence I know what type is in the semantic stack. – Parsa Noori Feb 03 '22 at 12:52

2 Answers2

5
  1. std::any is for storing objects of any type (limitations may apply).

However, the entire design of storing any type is rarely ideal. Often, it's better to use variadic templates to keep polymorphism entirely compile time, or to have only a limited set of types (std::variant), or even to use an OOP hierarchy. Which is more appropriate depends on the use case.

eerorika
  • 232,697
  • 12
  • 197
  • 326
-3

void* pointers is a pure C stuff that is obsolete in C++. You can use use smart pointers (such as unique_ptr or shared_ptr) when you dynamically allocate memory for your objects/variables/members. Do not wrap some API pointer objects that is not created by you in smart pointer objects. When you pass arguments into a function and you need to avoid copying of objects you better use references instead of pointers. However, you can use raw pointers in C++ but this is not recommended.

  • "However, you can use raw pointers in C++ but this is not recommended." A lot of things can be "not recommended" if you're not using stuff properly. If I care about performance, I'm 100% going to use raw pointers. If ownership isn't tangible, I'm also going to use raw pointers. – Visual Studio Feb 03 '22 at 03:42
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – mohammad mobasher Feb 03 '22 at 06:25
  • You are just repeating the question. – Parsa Noori Feb 03 '22 at 12:50