Help in Stacks

Hello. I've been studying stacks and I just want to know on how to modify this code below, wherein, This program can accept any data types. Can someone help me on how to fix this code below? Any help will do. Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <stack>
using namespace std;


void printStackElements (stack<int><float><string> stack) 
{
   while (!stack.empty()) 
   {
       cout << stack.top() << endl;
       stack.pop();
   } 
}

int main()
{ 
    
    stack<int>numbersStack;
    numbersStack.push(1);
    numbersStack.push('a');
    numbersStack.push(1.34);
    numbersStack.push(4);
    numbersStack.push(5);
  
    printStackElements(numbersStack);
   
}
Last edited on
A stack can contain only elements of one type. Using templates you can have a function that accepts a stack of a templated param. eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <stack>

template <typename T>
void printStackElements(std::stack<T> stack) {
	while (!stack.empty()) {
		std::cout << stack.top() << '\n';
		stack.pop();
	}
}

int main() {
	std::stack<int> numbersStack;

	numbersStack.push(1);
	numbersStack.push(4);
	numbersStack.push(5);

	printStackElements(numbersStack);

	std::stack<double> stkdbl;

	stkdbl.push(4.567);
	stkdbl.push(1.34);

	printStackElements(stkdbl);
}



5
4
1
1.34
4.567


Since C++17, there are two types std::variant and std::any that can hold values of different types. You can have a std::stack of these types. However these aren't simple types to use.

https://en.cppreference.com/w/cpp/utility/variant
https://en.cppreference.com/w/cpp/utility/any
As an example, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <stack>
#include <variant>

using VarT = std::variant<int, double, char>;

void printStackElements(std::stack<VarT> stack) {
	const auto PrintVisitor { [](const auto& t) { std::cout << t << '\n'; } };

	while (!stack.empty()) {
		std::visit(PrintVisitor, stack.top());
		stack.pop();
	}
}

int main() {
	std::stack<VarT> stk;

	stk.push(1);
	stk.push(1.34);
	stk.push('a');

	printStackElements(stk);
}



a
1.34
1

> how to modify this code below, wherein, This program can accept any data types.

Accept any data type that can be sent to an output stream.

C++20:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <concepts>
#include <variant>
#include <stack>
#include <list>
#include <string>

template < typename T > 
concept output_streamable = requires( const T& v, std::ostream& stm ) { { stm << v } -> std::same_as<std::ostream&> ; } ;

template < output_streamable T, typename CNTR > // print the contents of a stack of an output_streamable type
void print_elements( std::stack<T,CNTR> stk, std::ostream& stm = std::cout ) 
{
	while( !stk.empty() )
	{
		stm << stk.top() << '\n' ;
		stk.pop() ;
	}
	stm << "-----------------------\n" ;
}

template < output_streamable... T > // a variant of output_streamable types is also output_streamable
std::ostream& operator<< ( std::ostream& stm, const std::variant<T...>& var )
{
	static const auto printer = [&stm]( const output_streamable auto& v ) -> std::ostream& { return stm << v ; } ;
	return std::visit( printer, var ) ;
}

int main()
{
	std::stack<int> stkint ;
	std::stack< double, std::list<double> > stkdbl ;
	std::stack < std::variant<std::string,double> > stkvar ; // string or double

	for( int v = 0 ; v < 10 ; ++v )
	{
		stkint.push(v) ;
		stkdbl.push( 1.0 / (v+3) ) ;
		if( v%2 == 1 ) stkvar.push( "###" + std::to_string(v+100) + "+++" ) ; // string
		else stkvar.push( 1.0 / (v+3) ) ; // double
	}
	
	print_elements(stkint) ;
	print_elements(stkdbl) ;
	print_elements(stkvar) ; // fine: both std::string and double are output_streamable

	struct AAA {} ; std::stack<AAA> stkaaa ;
	// print_elements(stkaaa) ; // *** error *** no matching function; constraint not satisfied (AAA is not output_streamable) 

	std::stack< std::variant<AAA,int,double> > stkaid ; // AAA or int or double
	// print_elements(stkaid) ; // *** error *** no matching function (std::variant<AAA,int,double>  is not output_streamable) 
}
printStackElements() is very inefficient as it first copies the stack (as the param is passed by value) then it destroys the copied stack as it prints the top element in each loop iteration. Using std::stack, there's not really an efficient way of doing this as you're not provided with a mechanism to access stack elements other than the top one - not even begin() and end()!

However, std::stack is based around another container (dequeue by default) and the various elements of these can be accessed. If a new class is derived from std::stack then you can have function(s) in this derived class that directly access the stack's elements. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <stack>
#include <variant>

using VarT = std::variant<int, double, char>;

template<typename T>
class MyStack : public std::stack<T> {
public:
	using std::stack<T>::stack;

	void print() {
		const auto PrintVisitor { [](const auto& t) { std::cout << t << '\n'; } };

		for (auto itr { this->c.crbegin() }; itr != this->c.crend(); ++itr)
			std::visit(PrintVisitor, *itr);
	}
};

int main() {
	MyStack<VarT> stk;

	stk.push(1);
	stk.push(1.34);
	stk.push('a');

	stk.print();
}



a
1.34
1


which is much more efficient as display just iterates the stack container.
Last edited on
Topic archived. No new replies allowed.