Skip to main content
gamedev.net
🔒 Locked

Template code errors

Started by Eriond Jun 11, 2004 at 3:28 PM 5 replies 450+ views
Original Post
Eriond
Eriond
I''m reading C++ Templates The complete guide and try to compile the stack example found on page 52-54 in vc++ 7.1
template<typename T, template <typename Elem, typename = std::allocator<Elem> >
							   class Container = std::deque>
class Stack
{
public:
	void Push(const T &);
	void Pop();
	T Top() const;
	bool Empty() const { return elems.empty(); }

	template<typename T2, template<typename Elem2, typename = std::allocator<Elem2> >
		class Container2>
	Stack<T, Container> &operator=(const Stack<T2, Container2> &);
private:
	Container<T> elems;
};

template<typename T, template<typename, typename> class Container>
void Stack<T, Container>::Push(const T &elem)
{
	elems.push_back(elem);
}

template<typename T, template<typename, typename> class Container>
void Stack<T, Container>::Pop()
{
	if (elems.empty())
	{
		throw std::out_of_range("Stack<>::Pop(): empty stack");
	}
	elems.pop_back();
}

template<typename T, template<typename, typename> class Container>
T Stack<T, Container>::Top() const
{
	if (elems.empty())
	{
		throw std::out_of_range("Stack<>::Top(): empty stack");
	}
	return elems.back();
}

template<typename T, template<typename, typename> class Container>
  template<typename T2, template<typename, typename> class Container2>
Stack<T, Container> &Stack<T, Container>::operator=(const Stack<T2, Container2> & op2)
{
	if (static_cast<void *>(this) == static_cast<void *>(&op2))
	{
		return *this;
	}
	Stack<T2, Container2> temp(op2);
	elems.clear();
	while (!temp.Empty())
	{
		elems.push_front(temp.Top());
		temp.Pop();
	}
	return *this;
}
I get two errors when I try to compile it: error C3201: the template parameter list for class template ''std::deque'' does not match the template parameter list for template parameter ''Container'' error C2976: ''Container'' : too few template arguments I have looked over the code a few times and don''t find any differences from the books code, except for the names.
snk_kid
snk_kid

#include <deque>
#include <cstddef>

template< typename T, typename _alloc = std::allocator<T>,
template < typename, typename > class Container = std::deque >
class Stack {
public:
typedef typename Container< T, _alloc >::iterator iterator;
typedef typename Container< T, _alloc >::const_iterator const_iterator;

typedef T value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef ::ptrdiff_t difference_type;
typedef ::size_t size_type;

void Push(const T &);
void Pop();
T Top() const;
bool Empty() const { return elems.empty(); }

template< typename type, typename _alloc2,
template < typename, typename > class Container2 >
Stack< T, _alloc, Container >& operator=(const Stack< type, _alloc2, Container2 >& );
private:
Container< T, _alloc > elems;
};


i'll leave the rest to you.

[edited by - snk_kid on June 11, 2004 7:10:28 PM]
quant
quant
I think its a problem with 7.1 standards compliance, the code compiles fine in mingw32 3.2.
-keyboard
Eriond
Eriond
snk_kid: That just adds lots of errors If I change my code in the beginning to:
template<typename T, template <typename Elem, typename Alloc = std::allocator<Elem> >
class Container = std::deque>
Now I get rid of the first error but the second remains. If I try to change Container to Container, the compiler says Alloc is an undeclared indentifier.
snk_kid
snk_kid
Your first code post wont compile under VS.NET 7.1 it works under gcc also changing it to what you've just posted wont get accepted, i've given you an alternative that does compile on VS.NET 7.1 under it but i didn't implement those methods, you'll have to post your changed version so we can see what you've done in your method.

[edited by - snk_kid on June 12, 2004 8:14:13 AM]
snk_kid
snk_kid
Obviously you haven''t updated your code to reflect the changes in the alternative version i gave you thats why your getting errors, well i''ve changed it all for you with an implementation that compiles & runs on GCC 3.4 & VS.NET 7.1 and with a test example to go with it:

stack.hpp

#ifndef _STACK_HPP_
#define _STACK_HPP_
#include <cstddef>
#include <stdexcept>
#include <deque>

template< typename T, typename _alloc = std::allocator<T>,
template < typename, typename > class Container = std::deque >
class stack {
public:

typedef typename Container< T, _alloc >::iterator iterator;
typedef typename Container< T, _alloc >::const_iterator const_iterator;

typedef T value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef ::ptrdiff_t difference_type;
typedef ::size_t size_type;

stack(): elems() {}
void push(const_reference);
void pop();
reference top();
const_reference top() const;

bool empty() const { return elems.empty(); }

template< typename type, typename _alloc2,
template < typename, typename > class Container2 >
stack< T, _alloc, Container >& operator=(const stack< type, _alloc2, Container2 >& );
private:
Container< T, _alloc > elems;
};

template< typename T, typename _alloc,
template < typename, typename > class Container >
inline void stack< T, _alloc, Container >::push(const T& elem) {
elems.push_back(elem);
}

template< typename T, typename _alloc,
template < typename, typename > class Container >
inline void stack< T, _alloc, Container >::pop() {
if(elems.empty()) {
throw std::out_of_range("Stack<>::Pop(): empty stack");
}
elems.pop_back();
}

template< typename T, typename _alloc,
template < typename, typename > class Container >
inline const T& stack< T, _alloc, Container >::top() const {
if (elems.empty()){
throw std::out_of_range("stack<>::top(): empty stack");
}
return elems.back();
}

template< typename T, typename _alloc,
template < typename, typename > class Container >
inline T& stack< T, _alloc, Container >::top() {
if (elems.empty()){
throw std::out_of_range("stack<>::top(): empty stack");
}
return elems.back();
}


template< typename T, typename _alloc,
template < typename, typename > class Container >
template< typename type, typename _alloc2,
template < typename, typename > class Container2 >
stack< T, _alloc, Container >&
stack< T, _alloc, Container >::operator=(const stack< type, _alloc2, Container2 >& op2) {
if(this == &op2) {
return *this;
}

stack< type, _alloc2, Container2 > temp(op2);

elems.clear();
while (!temp.Empty()) {
elems.push_front(temp.Top());
temp.pop();
}

return *this;
}
#endif


main.cpp

#include "stack.hpp"
#include <cstdlib>
#include <iostream>
int main() {

stack< int > my_ints;

my_ints.push(3);
my_ints.push(45);
my_ints.push(53);

int& t = my_ints.top();

std::cout << t << std::endl;

return EXIT_SUCCESS;
}
Eriond
Eriond
I haven't been online for a while so I could not post my code. Thanks for the example Do you know if there are any plans on fixing this in VS 2005?

Edit: It still does not seem to fix the problem the example in the book was trying to solve. To be able to create a stack lite this: stack<int, std::vector> s; Do I have to change that to something else?

Edit2: I solved it :D Nearly the same code I posted in the first post.
template<typename T, template <typename Elem, typename Alloc = std::allocator<Elem> >
class Container = std::deque>
class Stack
{
public:
Stack(): elems() {}
void Push(const T &);
void Pop();
T &Top();
const T &Top() const;

bool Empty() const { return elems.empty(); }

template<typename T2, template <typename, typename> class Container2>
Stack<T, Container> &operator=(const Stack<T2, Container2> &);
private:
Container<T, std::allocator<T> > elems;
};

template<typename T, template <typename, typename> class Container>
inline void Stack<T, Container>::Push(const T &elem)
{
elems.push_back(elem);
}

template<typename T, template <typename, typename> class Container>
inline void Stack<T, Container>::Pop()
{
if(elems.empty())
{
throw std::out_of_range("Stack<>::Pop(): empty Stack");
}
elems.pop_back();
}

template<typename T, template <typename, typename> class Container>
inline const T& Stack<T, Container>::Top() const
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::top(): empty Stack");
}
return elems.back();
}

template<typename T, template <typename, typename> class Container>
inline T& Stack<T, Container>::Top()
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::top(): empty Stack");
}
return elems.back();
}


template<typename T, template <typename, typename> class Container>
template<typename T2, template <typename, typename> class Container2>
Stack<T, Container> &Stack<T, Container>::operator=(const Stack<T2, Container2 > &op2)
{
if(this == (void *)&op2)
{
return *this;
}

Stack<T2, Container2> temp(op2);

elems.clear();
while (!temp.Empty())
{
elems.push_front(static_cast<T>(temp.Top()));
temp.Pop();
}
return *this;
}
Now I can use it like this: Stack<int, std::vector> s.

[edited by - Eriond on June 12, 2004 3:39:56 PM]

[edited by - Eriond on June 12, 2004 3:40:38 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.