Unresolved External Symbol Error

I am writing a templated stack class for a programming class, and I cannot for the life of me get it to compile.

My IDE is Visual Studio Professional 2013.

I previously had issues about visual studio thinking the constructor needed a return type defined, but that seems to have fixed itself.
Now Visual Studio is presenting me with 4 errors:
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall StackOfAnything<int>::StackOfAnything<int>(void)" (??0?$StackOfAnything@H@@QAE@XZ) referenced in function _wmain
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall StackOfAnything<int>::~StackOfAnything<int>(void)" (??1?$StackOfAnything@H@@QAE@XZ) referenced in function _wmain
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall StackOfAnything<char>::StackOfAnything<char>(void)" (??0?$StackOfAnything@D@@QAE@XZ) referenced in function _wmain
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall StackOfAnything<char>::~StackOfAnything<char>(void)" (??1?$StackOfAnything@D@@QAE@XZ) referenced in function _wmain
1>c:\users\kurt slagle\documents\visual studio 2013\Projects\StackOfAnything\Debug\StackOfAnything.exe : fatal error LNK1120: 4 unresolved externals

My code is below

for StackOfAnything.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  #ifndef STACK_OF_ANYTHING_H
#define STACK_OF_ANYTHING_H

#include "BoxOfAnything.h"
#include <stdexcept>

template<class T>
class StackOfAnything
{
public:
	StackOfAnything();
	~StackOfAnything();
	bool isEmpty() const;
	int size() const;
	void push(T value);
	T peek() const throw(std::runtime_error);
	T pop() throw(std::runtime_error);
private:
	BoxOfAnything<T>* m_top;
	int m_size;
};

#endif 


for StackOfAnything.cpp
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "StackOfAnything.h"
#include <iostream>
#include <stdexcept>

template<class T>
StackOfAnything<T>::StackOfAnyting()
{
	m_top = nullptr;
	m_size = 0;
}

template<class T>
StackOfAnything<T>::~StackOfAnything()
{
	while (!isEmpty())
		pop();
}

template<class T>
bool StackOfAnything<T>::isEmpty() const
{
	if (m_size > 0)
		return false;
	else
		return true;
}

template<class T>
int StackOfAnything<T>::size() const
{
	return m_size;
}

template<class T>
void StackOfAnything<T>::push(T value)
{
	BoxOfAnything<T>* temp = m_top;
	m_top = new BoxOfAnything < T > ;
	m_top->setValue(value);
	m_top->setPrevious(temp);
	m_size++;
}

template<class T>
T StackOfAnything<T>::peek() const throw(std::runtime_error)
{
	if (m_size <= 0)
		throw (std::runtime_error("Peek attempted on empty stack"));
	else
		return m_top->getValue();
}

template<class T>
T StackOfAnything<T>::pop() throw(std::runtime_error)
{
	if (!isEmpty())
	{
		T tempval = m_top->getValue();
		BoxOfAnything<T>* temp = m_top->getPrevious();
		delete m_top;
		m_top = temp;
		m_size--;
		return tempval;
	}
	else
		throw (std::runtime_error("Pop attempted on empty stack"));
}


for BoxOfAnything.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef BOX_OF_ANYTHING_H
#define BOX_OF_ANYTHING_H


using namespace std;


template<class T>
class BoxOfAnything
{
public:
	BoxOfAnything(T value);
	BoxOfAnything<T>* getPrevious();
	T getValue();
	void setValue(T value);
	void setPrevious(BoxOfAnything<T>* next);

private:
	BoxOfAnything<T>* m_previous;
	T m_value;
};

#endif 


for BoxOfAnything.cpp
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
#include "BoxOfAnything.h"

template<class T>
BoxOfAnything<T>::BoxOfAnything(T value)
{
	m_value = value;
	m_previous = nullptr;
}

template<class T>
BoxOfAnything<T>* BoxOfAnything<T>::getPrevious()
{
	return m_previous;
}

template<class T>
T BoxOfAnything<T>::getValue()
{
	return m_value;
}

template<class T>
void BoxOfAnything<T>::setValue(T value)
{
	m_value = value;
}

template<class T>
void BoxOfAnything<T>::setPrevious(BoxOfAnything<T>* next)
{
	m_previous = next;
}


I am NOT asking to get advice for improving my code. My class is very strict, and I am not allowed to use any other methods than the ones that I have already used (including other libraries, other macros, etc).

I have no idea why this is not compiling. Any help would be greatly appreciated.
I was able to write a regular stack project just fine, but this one, for some reason, just will not work. I love Visual Studio, but I hate it as well.

Thank you from a programmer who has been banging his head on his keyboard all morning.
Template-dependent functions must go in header files.
In this case, you must end up with no .cpp files associated.
I have changed the .cpp to .hpp, as I was told to do in my class, but it still does not resolve the issue. Am I to define the functions inside the header itself? I think that my course requires that I have separate header and implementation files.
Yes, you need to define the functions inside the header. This is only for template classes/member functions.
Last edited on
I changed it so that it is only .hpp and .h files, and included the .hpp files at the bottom of the header file.

It removed the linker errors, but I am now getting two different errors:
1>c:\users\kurt slagle\documents\visual studio 2013\projects\stackofanything\stackofanything\stackofanything.hpp(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\kurt slagle\documents\visual studio 2013\projects\stackofanything\stackofanything\stackofanything.hpp(10): error C2063: 'StackOfAnyting' : not a function
1>c:\users\kurt slagle\documents\visual studio 2013\projects\stackofanything\stackofanything\stackofanything.hpp(10): fatal error C1903: unable to recover from previous error(s); stopping compilation

Of course, that is for the constructor, which should not have a type specifier. Additionally, StackOfAnything is most certainly a function.

EDIT: I am supposed to be able to compile this on Linux (that is the only development environment that the university uses), and I was told that I needed to use .hpp and .h files to compile on Linux.
Last edited on
I'm not sure since I only define functions inlined in the first header.
Try switching from StackOfAnything<T>::StackOfAnyting() to StackOfAnything<T>::StackOfAnyting<T>().
Same for the destructor.

But, how I do it, it looks like the following:
1
2
3
4
5
6
template <typename T>
class tExample {
    tExample() {
        /* function body here */
    }
};


(The function body needs no changes, unless it contains errors)

Another thing:
Files don't really need to be named to .hpp and .h to be compiled on Linux.
Probably they just compile with the *.cpp filter, so this is not an issue as long as you don't use .cpp for headers, and you can either use .h or .hpp (but it is suggested you use .hpp for C++ headers, e.g. this one, but it really doesn't change anything since it gets copy-pasted to the .cpp file at the #include point).
Last edited on
Unfortunately, changing StackOfAnything<T>::StackOfAnything() to StackOfAnything<T>::StackOfAnything<T>() introduced a whole league of syntax errors.

Perhaps I should be attempting to use a different IDE?
IDEs rarely are the problem.
Oh wow, there's a typo there.
You wrote StackOfAnyting.
And, your version was correct.
(Note: Linker errors didn't depend from this typo)
Last edited on
Oh. Wow. I can't believe I missed that. I am also shocked that Visual Studio didn't tell me that I typed it incorrectly!

Here's to hoping that my stack works properly.
Thank you so much for your help!
May I make some suggestions?
The class itself seems to be working (Didn't really try it, but it seems to work as expected), but BoxOfAnything<T>::setPrevious and BoxOfAnything<T>::BoxOfAnything should be private and StackOfAnything<T> should be added as a friend to BoxOfAnything<T> as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <typename T>
class BoxOfAnything {
	friend class StackOfAnything<T>;
public:
	BoxOfAnything<T>* getPrevious();
	T getValue();
	void setValue(T value);

private:
	BoxOfAnything(T value);
	void setPrevious(BoxOfAnything<T>* next);
	BoxOfAnything<T>* m_previous;
	T m_value;
};

Function bodies, again, need no changes.
This allows for only StackOfAnything<T> to call and construct setPrevious.
And perhaps StackOfAnything<T>::m_size should be of type unsigned int so you shouldn't check for negativeness?
I'd also change from postincrement to preincrement:
From m_size++; and m_size--; to ++m_size; and --m_size;


Also, StackOfAnything<T>::isEmpty can be shortened to:
1
2
template<class T>
bool StackOfAnything<T>::isEmpty() const { return m_size > 0; }


In StackOfAnything.hpp, line 38, you can also change from:
1
2
3
	m_top = new BoxOfAnything<T>;
	m_top->setValue(value);
	m_top->setPrevious(temp);

to:
1
2
	m_top = new BoxOfAnything<T>(value);
	m_top->setPrevious(temp);


Don't do these changes unless you learnt it at school, though, or study what they do.
I could also list some more changes, but they will change a bit too much of the class, so I won't list them unless you want to hear them.

Oh, whoops:
JayZom wrote:
I am NOT asking to get advice for improving my code.

Whatever, let this post just slip away then, or study it on your own if you want to.
Last edited on
I apologize if I sounded like I was not open to advice and criticism. I am, of course, open to it.
I just cannot use some of these changes because of the way that I was told to write my program. I've learned some of these changes in school, most over a year ago in another class, but my programming lab TA (who grades all of my assignments) is very picky.

What is the advantage of adding StackOfAnything<T> as a friend to BoxOfAnything<T>?

If you have advice on how I could improve my code, please let me know. I'm more than happy to hear how I can improve!

Thank you very much!
Last edited on
Adding a class as a friend means letting that class access your private and protected members/functions.
This, plus setting setPrevious private, allows only StackOfAnything and BoxOfAnything to call setPrevious.
In this way, the users of the class cannot call setPrevious (not that they should anyways, but if they do, bad stuff could happen).
Again, note you shouldn't do these changes if you're not supposed to, but in real-world programs you should.
I actually did use one of your recommendations. I used m_top = new BoxOfAnything<T>(value). My program didn't want to compile otherwise (it said no appropriate default constructor was available).
I also changed to preincrement.

You're right. There is no reason for setPrevious to be public, as the only time I am calling it is from within the class itself. However, the assignment criteria was that the function be public, so I am stuck leaving it as so.

I think that might be a good change to make for my next project, after I can confirm whether or not I am allowed to do that. When making my own projects, I typically don't program in the same way that I do for classes. I typically program with as many things as private as possible, but my programming classes always ask for strange programming practices (as usually force us to use a particular syntax).

Visual Studio doesn't seem to be happy that I am trying to throw exceptions, but I believe that Linux shouldn't have an issue with it.

I'd be happy to hear your other recommendations, even if it changes the class a lot. I am studying to be a software engineer, so I need all the improvement I can get.
Well, other improvements are:
1. Remove the setPrevious function, and add its functionality from the BoxOfAnything constructor.
2. Make getValue and getPrevious const.
3. Pass "T" as const-Reference (You'll probably learn it soon about the differences. What happens "in practice" is, it is saving the operation to copy items to temporary parameters whenever possible).
4. Remove negative checks for unsigned int size.
5. Default "T" item construction
6. Deny BoxOfAnything item copy (optional, disables being able to copy a BoxOfAnything, not really required)
All the changes will make it look as follows:

BoxOfAnything Header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* ... */
template <typename T>
class BoxOfAnything {
	friend class StackOfAnything<T>;
public:
	BoxOfAnything<T>* getPrevious() const; // pt. 2
	T const& getValue() const; // pt. 2 and pt. 3
	void setValue(T const& value); // pt. 3

private:
	// C++ adds a default function if you don't
	// declare this in the header, allowing for BoxOfAnything to be copied.
	BoxOfAnything(BoxOfAnything<T> const&); // pt. 6. Doesn't need to have a body,
	// since we want this to be removed.
	// For c++11. use:
	//	BoxOfAnything(BoxOfAnything<T> const&) =delete;
	// void setPrevious(BoxOfAnything<T>* next); Erased: pt. 1
	BoxOfAnything(T const& value, BoxOfAnything<T>* prev) // pt. 1 and pt. 3
	BoxOfAnything<T>* m_previous;
	T m_value; // must not be const-ref in this case. Keep this as a simple T.
};
/* ... */


BoxOfAnything Function Definitions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* ... */
template<class T> BoxOfAnything<T>::BoxOfAnything(T const& value, BoxOfAnything<T>* prev) // pt. 1 and pt. 3
{
	m_value = value;
	m_previous = prev; // pt. 1
}

template<class T> BoxOfAnything<T>* BoxOfAnything<T>::getPrevious() const // pt. 2
/* no body changes */

template<class T> T const& BoxOfAnything<T>::getValue() const // pt. 2 and pt. 3
/* no body changes */

template<class T> void BoxOfAnything<T>::setValue(T const& value) // pt. 3
/* no body changes */

// template<class T> void BoxOfAnything<T>::setPrevious(BoxOfAnything<T>* next)
// Erased: pt. 1

/* ... */


StackOfAnything Header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* ... */
template<class T>
class StackOfAnything
{
public:
	StackOfAnything();
	~StackOfAnything();
	bool isEmpty() const;
	unsigned int size() const; // pt. 4
	void push(T const& value =T()); // pt. 3 and pt. 5. Note: " = T() " only goes in headers.
		// The value parameter is now optional, and if it is not specified,
		// T() is used instead, which is a parameterless(default?)-constructed T type item.
		// If a T item does not have a parameterless constructor, you can still use this class.
		// Must not be const-ref.
	T const& peek() const throw(std::runtime_error); // pt. 3
	T const& pop() throw(std::runtime_error); // pt. 3
private:
	BoxOfAnything<T>* m_top;
	unsignde int m_size; // pt. 4
};
/* ... */


StackOfAnything Function Definitions:
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
/* ... */

template<class T>
bool StackOfAnything<T>::isEmpty() const
{
	// pt. 4
	return !!m_size; // !(!m_size)
				// With builtins, kind of a "m_size != 0", you can use either one at your choice.
				// Also "m_size > 0" is valid, but requires slightly more computations (very very slightly)
				// But since we're now using unsigned m_size, it cannot be under 0 in any case.
}

template<class T>
unsigned int StackOfAnything<T>::size() const // pt. 4
/* no body changes */

template<class T>
void StackOfAnything<T>::push(T const& value) // pt. 3. No changes for pt. 5.
{
	// pt. 1
	BoxOfAnything<T>* temp = m_top;
	m_top = new BoxOfAnything<T>(value,temp);
	++m_size; // "tactical" preincrement
}

template<class T>
T const& StackOfAnything<T>::peek() const throw(std::runtime_error) // pt. 3
{
	if (isEmpty()) // for consistency with pop(), use isEmpty().
		throw std::runtime_error("Peek attempted on empty stack"); // doesn't really need parenthesis
	else
		return m_top->getValue();
}

template<class T>
T const& StackOfAnything<T>::pop() throw(std::runtime_error) // pt. 3
{
	if(!isEmpty())
	{
		T tempval = m_top->getValue(); // Note: must not be a const&
		BoxOfAnything<T>* temp = m_top->getPrevious();
		delete m_top;
		m_top = temp;
		--m_size; // "tactical" predecrement
		return tempval;
	}
	else
		throw std::runtime_error("Pop attempted on empty stack"); // no parenthesis too
}
/* ... */


Going with further edits will require you to have more knowledge of Standard Library stuff, and using C++11 (such as constructing a T item with an arbitrary parameter list).

If you would really like to know more about what happens, you should try to find a book online (or even a printed one, if you can find one. I wish I did, because I hate reading text on screen).
Last edited on
Wow, thanks!

I see what you mean. My code could use some optimization. I think the changes that you recommend push the limits of my understanding of C++ so far, but I definitely see how the improvements can make my program more efficient and safe from accidents.

Sorry for the strange exception throwing syntax - that was just how it was introduced in class.

The classes I am taking do not like to introduce optimizations or short-hand ways of doing things. For some reason, they want us to do it the long way around. I think the reason why is because most of the students in my class only know Java, but I have two years of C++ under my belt, so I'm stuck in a class that is doing things that I pretty much already know how to do. Sometimes I mix C and C++, but I can only do so on solo projects.

I am supposed to learn about inputting assembly into my programs next semester - I hear that is supposed to help increase the efficiency of my program.

Perhaps I will learn more when I take Software Engineering I next semester (as well as my potential internship next summer).

Do you have any recommendations for books? I really prefer printed books - I have never been one to like electronic books. I just don't like reading long texts on a computer screen. It just isn't the same, you know?

Again, thank you for all your help! I will ask my instructor and see if I am allowed to use any of your recommendations in my future programs!
Well, I've read not so many books, like:
- Addison Wesley's C++ Templates: The Complete Guide
- Herb Sutter's Exceptional C++ and More Exceptional C++
And some others, more related to not just C++, like:
- Charles Petzold's Programming Windows
- OpenGL Specs (Both Blue and Redbook, and the 4.2 OpenGL/GLSL specs)

Most of what I've learnt about templates, I've learnt it from books.
What wasn't for a template, I've learnt it from this forum, or some googling.
Topic archived. No new replies allowed.