unresolved external symbol referenced in function.

Hello, I'm trying to implement a template in to my code so I can use multiple linked lists, all with different data types. An error has appeared in my source.cpp file in my main() function. It says "unresolved external symbol _main referenced in function "int _cdecl invoke_main (void)" (? invoke_main@@Y AHXZ)". It also says that there's one 1 unresolved external but I know from internet sleuthing that that error is referring to the error above it.

At first I thought that I hadn't included the right h files or that I needed to get rid of all references to int in my code since I was using a template now. None of those things have yielded any results yet. The most frustrating thing about this error is I can only assume it's in main because the error mentions main and void. There's no red underline for the problematic code and it just says the error's on line one which I also know is not true and just a generic answer the error gives.

Help would be appreciated.

Source.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
#include "Node.h"
#include "TempLinkedList.h"
template<typename T>
void Testone()
{
	TempLinkedList* list = new TempLinkedList();

	TempNode* m_head1 = new TempNode("2");
	TempNode* m_head2 = new TempNode("4");
	TempNode* m_head3 = new TempNode("6");
	TempNode* m_head4 = new TempNode("8");
	TempNode* m_head5 = new TempNode("10");
	TempNode* m_head6 = new TempNode("12");
	list->PushBack(m_head1);
	list->PushBack(m_head2);
	list->PushBack(m_head3);
	list->PushBack(m_head4);
	list->PushBack(m_head5);
	list->PushBack(m_head6);
	list->Execute();

}
template<typename T>
void main()
{
	Testone<T>(); // Testone isn't coloured in like the rest of the code so 
                      //I suspect that's where the problem is really going 
                      //wrong. I don't know why though.
	TempNode<T> TTempNode;
	T numAdd = TTempNode.GetNext();

	system("pause");
}


My Linked list and Node classes in case it's a problem with those:

TempLinkedList:

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
#pragma once
#include <iostream>
#include "Node.h"
template<typename T>
class TempLinkedList
{
public:
	TempLinkedList();
	TempNode<T>* GetHead();

	void PushBack(T data, T m_node);

	void Execute();

private:
	T* m_head;
};

template<typename T>
TempLinkedList<T>::TempLinkedList()
{
	m_head = nullptr;
}

template<typename T>
inline TempNode<T>* TempLinkedList<T>::GetHead()
{
	return m_head;
}



template<typename T>
void TempLinkedList<T>::PushBack(T data, T m_node)
{
	TempNode* temp = m_head;
	if (m_head == nullptr)
	{
		m_head = m_node; 
		return;
	}
	while (temp->GetNext() != nullptr)
	{
		temp = temp->GetNext();
	}
	temp->SetNext(m_node); 
}

template<typename T>
void TempLinkedList<T>::Execute()
{
	TempNode* temp = m_head;
	while (temp != nullptr)
	{
		temp->Execute();
		temp = temp->GetNext();
	}
}


Node.h:

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
#pragma once
#include <string>
#include <iostream>
using namespace std;
template<typename T>
class TempNode
{
public:
	TempNode(string* data, int* m_node)
	{
			data = new T[];
	}
	

	TempNode(T data, T next, T m_node);
	~TempNode();

	void SetNext(T* next);
	T* GetNext();
	T GetData();

	void execute();
private:
	T data;
	T next;
	T m_node;
	T TTempNode;

};

template<typename T>
TempNode<T>::TempNode(T data, T next, T m_node)
{
	this->data = data;
	this->next = nullptr;
	this->m_node = m_node;
}

template<typename T>
TempNode<T>::~TempNode()
{
}

template<typename T>
T* TempNode<T>::GetNext()
{
	return next;
}

template<typename T>
void TempNode<T>::SetNext(T* next)
{
	this->next = next;
}

template<typename T>
T TempNode<T>::GetData()
{
	return data;
}

template<typename T>
void TempNode<T>::execute()
{
	std::cout << data << std::endl;
}

main() can't be a template.
Peter87. If you mean getting rid of the template<typename T> over the main function. I've done what you said and have gotten even more errors. Mostly complaining about not identifying T. It also hasn't gotten rid of the original error.
Last edited on
is there template stuff in the cpp files? It should be in header files only.
main is of type int, other types are not standard c++ even if it works (minor).
Last edited on
jonnin. I've tried what you suggest. I still get the error.
Pogramming wrote:
If you mean getting rid of the template<typename T> over the main function. I've done what you said and have gotten even more errors.

Yes, that is what I mean.

More error messages doesn't necessarily mean you're making things worse. I recommend focusing on the first error. Fix it, recompile and repeat until you have no errors.

Pogramming wrote:
Mostly complaining about not identifying T.

It's because you're not specifying the template argument when using the class templates...

1
2
3
4
5
TempLinkedList<T>* list = new TempLinkedList<T>();

TempNode<T>* m_head1 = new TempNode<T>("2");
TempNode<T>* m_head2 = new TempNode<T>("4");
...
Last edited on

It's because you're not specifying the template argument when using the class templates...


Such a simple oversight! Oh well, slightly less errors now but it's still saying that the T in TempNode<T>* is an <<error type>>, or at least this is how I interpret it.

It also says T in Testone<T>(); is unidentified. Just putting <T> on to the void Testone(); would probably throw up an error. I'm not sure what's wrong here since I've done #include for the relevant files and I think declaring the variable wouldn't make sense because that would use template<typenameT> over main, which would just put me in the same problem...
Oh my,
1
2
3
4
5
6
7
8
9
template<typename T> // main() cannot be a template
void main() // return type of main() must be int
{
  Testone<T>(); // What is type T?
  TempNode<T> TTempNode; // What is type T?
  T numAdd = TTempNode.GetNext(); // What is type T?
  system("pause"); // Sticky thread on forum tells how to keep terminal open.
  // This is not not the way
}


One would expect:
1
2
3
4
5
6
int main()
{
  Testone<double>(); // real type
  TempNode<std::string> TTempNode; // another real type
  auto numAdd = TTempNode.GetNext(); // real type, compiler figures it out
}

Last edited on
Don't have using namespace in a header file.

1
2
3
4
TempNode(string* data, int* m_node)
	{
			data = new T[];
	}


T can only be of type string - otherwise the assignment will fail.
seeplus wrote:
T can only be of type string - otherwise the assignment will fail.

That's not the only problem with that line of code.
If it's actually supposed to create an array (which I doubt) then it also needs a size.
And you probably don't want to assign the pointer to a function parameter...

There are obviously a lot of issues with the code but I don't think it's worth trying to point them all out because many of them will probably be pretty obvious for the OP to fix once he/she starts to test and instantiate the templates with concrete types.
Last edited on
Hello again, I have made some progress on the code now. The only (visible) error is on line 67. It is saying that identifier is unexpected and that it expects a type of specifier. Does it mean specifiers like ints, floats, strings ect? In which case this doesn't make sense since this is the code that creates the linked list.

Node.h:

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
 template<typename T> // the Testone() code is now in Node.h because it was 
                     //throwing errors about the number declariton using 
                     //TempNode.
void Testone()
{
	TempLinkedList<T>* list = new TempLinkedList(); // error given, 
                                                        //specifically with the 
                                                        //TempLinkedList after 
                                                        //"new".

	TempNode<T>* m_head1 = new TempNode("2");
	TempNode<T>* m_head2 = new TempNode("4");
	TempNode<T>* m_head3 = new TempNode("6");
	TempNode<T>* m_head4 = new TempNode("8");
	TempNode<T>* m_head5 = new TempNode("10");
	TempNode<T>* m_head6 = new TempNode("12");
	list->PushBack(m_head1); 
	list->PushBack(m_head2); 
	list->PushBack(m_head3);
	list->PushBack(m_head4);
	list->PushBack(m_head5);
	list->PushBack(m_head6);
	list->Execute();

}


If it's actually supposed to create an array (which I doubt) then it also needs a size.
And you probably don't want to assign the pointer to a function parameter...


It doesn't, you are correct.
Last edited on
1
2
// TempLinkedList<T>* list = new TempLinkedList();
TempLinkedList<T>* list = new TempLinkedList<T>();
it expects a type

Indeed. The TempLinkedList is not a type. It is name of a template.

Lets look at:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename T>
struct TempLinkedList {
  T y;
};

template <typename U>
void Testone()
{
  TempLinkedList<U> x;
}

int main()
{
  Testone<int>();
}

Now we compile. The only concrete thing is:
1
2
3
4
int main()
{
  Testone<int>();
}

There is a function call, so compiler must create implementation for that function from template, and use U = int
Essentially, compile:
1
2
3
4
void Testone<int>()
{
  TempLinkedList<int> x;
}

There is a variable x, so compiler must create implementation for that object from template, and use T = int
Essentially, compile:
1
2
3
struct TempLinkedList<int> {
  int y;
};

If we had:
1
2
3
4
void Testone<int>()
{
  TempLinkedList z;
}

Then what is the type of z?
Then what is the type of z?


Int?


// TempLinkedList<T>* list = new TempLinkedList();
TempLinkedList<T>* list = new TempLinkedList<T>();


Should have laid out all the solutions I've tried, like that one, sorry but no change.
Last edited on
Pogramming wrote:
Int?

The type of x in keskiverto's example is TempLinkedList<int>.
 
TempLinkedList<int> x;

It might look like z will have the type TempLinkedList, but TempLinkedList is not a type so the code would not compile.
 
TempLinkedList z; // error 

Pogramming wrote:
Should have laid out all the solutions I've tried, like that one, sorry but no change.

What keskiverto showed you is right. You need to specify the template argument when creating the object with new. You also need to do this with the TempNodes.

You will still get errors after fixing those problems because the class templates TempLinkedList and TempNode are not implemented correctly. For example, if T represent the type of the elements that you want to store in the list then the type of m_head should probably not be T*. It should probably be something like TempNode<T>* instead. TempNode also needs some adjustments. All of the member variables should probably not have type T (though I have no idea what m_node and TTempNode are for).
Last edited on
A general tip here is to compile early, compile often. You should have tried to compile the code before you wrote multiple functions; that would have limited the scope of the issues you ended up having.
Ganado wrote:
compile early, compile often

This is a good advice but with templates you often don't get error messages unless the class template and its member functions are actually instantiated. This is especially true with MSVC.
... and test! Then you'll get the instantiations - and the compile errors!

> If you have:
> TempLinkedList z;
> Then what is the type of z?

Int?

Feels like you are guessing.
The line does not read: Int z;

Why do you think that the type would be Int?
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <string>

template < typename T > struct list // assumption: T is copy consructible ie. template < std::copy_constructible T >
{

    list() = default ; // initialise head and tail to nullptr
    ~list() { while( !empty() ) pop_front() ; } // release owned resources (nodes) on destruction

    bool empty() const noexcept { return head == nullptr ; }

    void push_back( const T& v )
    {
        if( empty() ) head = tail = new node(v) ;
        else
        {
            tail->next = new node(v) ;
            tail = tail->next ;
        }
    }

    void pop_front() noexcept
    {
        if( !empty() )
        {
            node* t = head ;
            head = head->next ;
            if( empty() ) tail = nullptr ;
            delete t ;
        }
    }

    void print( std::ostream& stm = std::cout ) const
    {
        std::size_t slno = 0 ; // zero-based serial number
        for( const node* n = head ; n != nullptr ; n = n->next )
            stm << "(#" << slno++ << "). " << n->data << " => " ;

        stm << "nullptr\n" ;
    }

    private:

        struct node // node is an implementation detail
        {
            T data ;
            node* next ;
            explicit node( const T& data, node* next = nullptr ) : data(data), next(next) {}
        };

        node* head = nullptr ;
        node* tail = nullptr ;

        // non-copyable and non-asignable (for now)
        list( const list& ) = delete ;
        list& operator= ( const list& ) = delete ;
};

// test list of T by inserting items from the input range one by one,
// and then removing items one by one till the list is empty
// assumption: input range contains a sequence of values which can be implicitly converted to T
// ie. template < typename T, std::ranges::input_range INPUT_RANGE > requires std::constructible_from< T, std::ranges::range_value_t<INPUT_RANGE> >
template < typename T, typename INPUT_RANGE > void test( const INPUT_RANGE& input_range )
{
     std::cout << "\n-----------------------------------------\n" ;

     list<T> lst ; // there is no good reason to create the list using new

     for( const auto& v : input_range )
     {
         lst.push_back(v) ;
         lst.print() ;
     }

     std::cout << '\n' ;

     while( !lst.empty() )
     {
         lst.pop_front() ;
         lst.print() ;
     }

     std::cout << "\n-----------------------------------------\n" ;
}

int main()
{
    const int a[] { 123, 234, 345, 456, 567, 678, 789 } ;
    test<int>(a) ;

    const char* const b[] { "cero", "uno", "dos", "tres", "cuatro", "cinco" } ;
    test<std::string>(b) ; // can convert const char* to std::string
}

http://coliru.stacked-crooked.com/a/2b4fc9135b405533
Topic archived. No new replies allowed.