Reputation: 13
I'm creating doubly linked list which has different types with template.
here is header and main code.
#ifndef UNV_LIST
#define UNV_LIST
#include <typeinfo>
using namespace std;
class node_base{
public:
node_base *next;
node_base *prev;
node_base () { next = 0; prev = 0; }
virtual int get_node_size () = 0;
};
template <typename T>
class node : public node_base{
public:
T data;
node (const T& val) : data(val) {}
virtual int get_node_size () { return sizeof (data); }
T getData () { return data; }
};
class unvlist{
node_base *head;
public:
int len;
unvlist ();
template <typename T> unvlist (const T* arr, int n);
~unvlist ();
template <typename T> void set (int n, const T& val);
template <typename T> T get (int n);
template <typename T> T insert (int n, const T& val);
void erase (int n);
int size ();
void pop_back ();
void pop_front ();
template <typename T> void push_back (const T& val);
template <typename T> void push_front (const T& val);
};
unvlist :: unvlist (){
head = 0;
len = 0;
}
/* I want to use this function without <> */
template <typename T>
T unvlist :: get (int n){
T retval;
if (n >= len || n < 0){
cout << "'In unvlist::get'-> Out of Bound!!!" << endl;
return 0;
}
if (n >= 0){
node_base *h = head;
for (int i = 0; i < n; i++) { h = h->next; }
retval = static_cast<node<T>*>(h)->getData ();
cout << retval << endl;
}
return retval;
}
template <typename T>
void unvlist :: push_back (const T& val){
node_base *n = new node<T> (val);
if (head == NULL){
head = n;
len++;
}else{
node_base *h = head;
while (h->next != NULL) { h = h->next; }
h->next = n;
n->prev = h;
len++;
}
}
template <typename T>
void unvlist :: push_front (const T& val){
node_base *n = new node<T> (val);
if (head == NULL){
head = n;
len++;
}else{
head->prev = n;
n->next = head;
head = n;
len++;
}
}
#endif
and main.cpp
#include <iostream>
#include "unvlist.hpp"
using namespace std;
int main (){
unvlist *l1 = new unvlist ();
l1->push_back<string> ("aa");
l1->push_back<char> ('A');
l1->push_back<float> (1.2345);
l1->push_front<int> (11);
for (int i = 0; i < 4; i++){
cout << l1->get (i) << endl; //The problem is here...
} cout << endl;
return 0;
}
I have to use the template function 'T get(int n)' without explicit <>. When I compiled it, however, there are some errors...
g++ -std=c++11 -Wall main.cpp -o main
main.cpp: In function 'int main()'
main.cpp:16:21: error: no matching function for call to 'unvlist::get(int&)'
cout << l1->get (i) << endl;
^
main.cpp:16:21: note: candidate is:
In file included from main.cpp:3:0:
unvlist.hpp:44:27: note: template<class T> T unvlist::get(int)
template <typename T> T get (int n);
^
unvlist.hpp:44:27: note: template argument deduction/substitution failed:
main.cpp:16:21: note: couldn't deduce template parameter 'T'
cout << l1->get (i) << endl;
^
make: *** [all] Error 1
'push_back' and 'push_front' function work well, but the problem is 'T get' function... Is there a way to use 'T get' function without <>?
Upvotes: 0
Views: 1168
Reputation: 1266
In terms of answering strictly what you've asked, no; the complier needs to know which version of get you're trying to call.
However you can achieve what it seems you're trying to do. If get were to return node_base by reference (or pointer), and node_base had a virtual operator>> that was overridden for each node then the type problem goes away.
If you consider the node_base class to be an implementation detail that shouldn't be exposed, then you could create another class for get to return instead (again a base class with type specific derived classes).
Upvotes: 0
Reputation: 1104
It is impossible to derive the type of the template parameter T for the function
T unvlist::get(int i)
having just such a call list->get(3)
.
You could modify your getter as follows:
template <typename T>
void unvlist :: get (int n, T &retval){
if (n >= len || n < 0){
cout << "'In unvlist::get'-> Out of Bound!!!" << endl;
}
if (n >= 0){
node_base *h = head;
for (int i = 0; i < n; i++) { h = h->next; }
retval = static_cast<node<T>*>(h)->getData ();
}
}
And use with a priory known resulting type:
int main (){
unvlist *l1 = new unvlist ();
l1->push_back<string> ("aa");
l1->push_back<string> ("A");
for (int i = 0; i < 2; i++){
std::string result; // we know std::string in advance
l1->get(i, result); // here compiler derives the T type correctly
std::cout << result << std::endl;
} cout << endl;
return 0;
}
Upvotes: 0
Reputation: 385174
I have to use the template function 'T get(int n)' without explicit <>
Well, you can't.
No arguments have anything to do with T
, so the compiler has no way of knowing what you want it to do. It cannot read your mind.
Upvotes: 1