For one of my school projects, I'm implementing a class which holds two separate containers, which are supposed to be stacks or queues based on which container the user specifies. My question is, is it possible to create two private member containers - let's call them container1 and container2 - and specify whether each is respectively a stack or a queue? (at construction)
Asked
Active
Viewed 57 times
-1
-
Are these [`std::stack`](https://en.cppreference.com/w/cpp/container/stack) and [`std::queue`](https://en.cppreference.com/w/cpp/container/queue)? – scohe001 Sep 13 '19 at 21:20
-
Is the type of each container determined at compile time or run-time? – Brady Dean Sep 13 '19 at 21:21
-
yes it's from the standard language – Patrick M Sep 13 '19 at 21:21
-
at runtime also – Patrick M Sep 13 '19 at 21:21
-
That sounds like a reasonable option, Patrick. The hard part will be making an interface that conceals the differences between the two from the user. You'd pretty much only be able to expose get, push, and pop methods. – user4581301 Sep 13 '19 at 21:22
-
basically they'd run ./main.exe -container1
, and when the class is created it would chose the type based on the command line input – Patrick M Sep 13 '19 at 21:23 -
Adding to @user4581301, you can make an interface over `std::stack` and `std::queue` and use a bit of inheritance to achieve what you want. Or if possible just do some if/else blocks and call whatever functions you need to on the stack/queue separately. – Brady Dean Sep 13 '19 at 21:25
-
1I was considering using a deque to represent both, and just implementing functions that will work with the deque like a stack or queue, but I think there's got to be a better way. – Patrick M Sep 13 '19 at 21:25
-
I'm familiar with inheritance but I don't really understand how id do that Brady. – Patrick M Sep 13 '19 at 21:26
-
Avoid inheriting directly from Standard Library classes. Few are intended for it. In general prefer [Composition over Inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance), ie make classes that contain stuff, rather than classes that inherit stuff. Also keep an eye on the [Liskov Substitution Principle](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle) when using inheritance. – user4581301 Sep 13 '19 at 21:29
-
@PatrickM Create 2 simple classes that contain a `std::stack` or `std::queue`. Both of these inherit from something like `Container` that has `push`, `pop`, and `get` methods. At run-time, check what the user wants and allocate either of the 2 classes into a `Container*`. – Brady Dean Sep 13 '19 at 21:29
-
@PatrickM `std::stack` uses a `deque` under the hood (by default) to begin with, so I don't see anything wrong with using a `deque` for both containers. – HolyBlackCat Sep 13 '19 at 21:29
-
1Using a single `deque` and changing how the interface behaves behind the scenes is an even better approach. – user4581301 Sep 13 '19 at 21:30
1 Answers
0
With template, you might have
template <typename Container1, typename Container2>
class MyClass
{
public:
// ....
private:
Container1 c1;
Container2 c2;
};
// Dispatch functions for non uniform code
template <typename T> void do_job_specific(std::stack<T>& s) {/*..*/}
template <typename T> void do_job_specific(std::queue<T>& d) {/*..*/}
// Common code
template <typename Container> void do_job_common(Container& d) {/*..*/}
and for main job
template <typename T> // would be MyClass<C1, C2>
void do_job()
{
T myClass;
// ...
}
enum class EContainer { Stack, Queue};
void dispatch_job(EContainer e1, EContainer e2)
{
using T1 = std::stack<int>;
using T2 = std::queue<int>;
if (e1 == EContainer::Stack) {
if (e2 == EContainer::Stack)) {
do_job<std::stack<T1, T1>>();
} else {
do_job<std::stack<T1, T2>>();
}
} else {
if (e2 == EContainer::Stack)) {
do_job<std::stack<T2, T1>>();
} else {
do_job<std::stack<T2, T2>>();
}
}
}
Now main
just have to call the method with selected enum from user.

Jarod42
- 203,559
- 14
- 181
- 302