This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 2 years ago.
I know people have asked similar questions in this area, but I can not seem to find a solution to my exact problem. I have a LinkedList and LinkedListIterator class structured as so.
template <typename T>
class LinkedList
{
public:
template <typename NodeType>
class LinkedListIterator
{
public:
const LinkedListIterator<NodeType>& operator++();
}
};
I am trying to implement the operator++() function in a separate file and my attempt is as follows.
template <typename T>
template <typename NodeType>
const typename LinkedList<T>::LinkedListIterator<NodeType>&
LinkedList<T>::LinkedListIterator<NodeType>::operator++()
{
// Implementation here
}
Now when I try to use this class, my compiler throws an error saying non-template ‘LinkedListIterator’ used as template. Now I know I have to use typename in the definition of this function since I have dependent scopes occurring. But I can not seem to be able to fix this. I do not understand how this is seen as non-template.
Add template keyword before LinkedListIterator so compiler knows it is a template and not e.g. a field
template <typename T>
template <typename NodeType>
const typename LinkedList<T>::template LinkedListIterator<NodeType>&
LinkedList<T>::LinkedListIterator<NodeType>::operator++()
{
// Implementation here
}
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 1 year ago.
I'm trying to create data structure for sorting data that will firstly receive any kind of object, i.e. int, string or MyCustomObject and then perform other tasks.
// heap.h
template <typename T>
class Heap{
public:
Heap();
~Heap();
}
//heap.cpp
template <typename T>
Heap<T>::Heap(){}
template <typename T>
Heap<T>::~Heap(){}
...
It turns out that from the very beginning when I try to run Heap<int> test it shows that classic message undefined reference to Heap<int>::Heap(). I found out that one workaround is to add template <typename int> at the end of the code.
However, if I try to do it with std::vector I'm pretty sure I can run std::vector<MyCustomObject> test which uses templates even without adding that line template<typename MyCustomObject> beforehand.
I want to know:
How would I perform this same behavior in my data structure of receiving "unknown" types?
Why std::vector implementation works whereas mine don't? What's missing?
To remove the undefined reference to Heap<int>::Heap() error you have to put the definition into the header file, too. Yes, that may seem strange, but that is the usual approach with templates:
heap.hpp:
template <typename T>
class Heap{
public:
Heap();
~Heap();
};
template <typename T>
Heap<T>::Heap(){}
template <typename T>
Heap<T>::~Heap(){}
main.cpp:
#include "heap.hpp"
int main()
{
Heap<int> test_with_int;
Heap<double> test_with_double;
return 0;
}
This question already has answers here:
std:: add_pointer, what the try_add_pointer for in the possible implementation?
(2 answers)
Closed 2 years ago.
I've been hacking around the standard library lately, since I need to implement a subset of it (mostly template stuff) for a system which doesn't have an stdlib implementation.
I came across this "possible implementation", in cppreference:
namespace detail {
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;
} // namespace detail
template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
and I've been wondering why do you need SFINAE here. Isn't this:
template< class T >
struct add_pointer {
typedef typename std::remove_reference<T>::type* type;
};
enough? which instantiation takes the second case of try_add_pointer? I tried to think about it but couldn't think about any such case.
I'm not sure if this is the only bad case, but your implementation fails for so-called "abominable function types":
add_pointer<void() const>::type // hard error instead of void() const
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 7 years ago.
I have the following code:
template <typename T>
struct Data {
struct Embed
{
T t;
};
};
struct Functor {
template <typename T>
void foo( typename Data<T>::Embed & e) {}
};
template <typename T, typename F>
struct Caller
{
F f;
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
};
Then I specialized the template as:
Caller<int, Functor> c;
c.invoke();
compiler error is : error: expected primary-expression before '>' in f.foo<T>(e); line. It seems compiler suddenly doesn't know what T is even it is specified in the template declaration on the function.
Take out the explicit specified T in foo.invoke(e) line will result could not deduce template parameter 'T'
How do I fix this? (I still want to keep the functionality that Caller can have generic functor and functor's function can be templated).
You are using:
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
inside Caller even though T is one of the parameters of Caller. Remove the line
template <typename T>
and use just:
void invoke() {
typename Data<T>::Embed e;
// f.foo<T>(e); //compiler error pointed this line
f.template foo<T>(e); // Need the template keyword here.
}
However, as #Nawaz pointed out in a comment, that changes the semantics of invoke. If T in invoke was meant to be different than the T used to instantiate Caller, then it will be better to use a different name, say U.
The problem is that f is of type F which is template parameter, f.foo is a dependent name and which happens to be a function template. So you've to use template in a very weird way:
f.template foo<T>(e);
For further explantion, see these:
short explanation
long explanation
Also, I'd advise you to use U as template parameter for the function template invoke if at all it needs to be a template, else you can make it a normal function (i.e if the T of invoke is ought to be same as T of the enclosing class template).
Hope that helps.
This question already has answers here:
When can I use a forward declaration?
(13 answers)
Closed 8 years ago.
for non-template class, I can use forward declaration in the header file. But it gave me error when I use it in the template class.
I have to include the header file, I would like to know the reason.
class Pu;
template <typename T>
class Pt()
{
void test(Pu<T> u);
}
It works just fine, if you do it properly!
Remember, Pu is a class template, not a class, so it must be declared as such:
template <typename T> // N.B. this line
class Pu;
template <typename T>
class Pt // N.B. no "()"
{
void test(Pu<T> u);
}; // N.B. ";"
(live demo)
So, I'm developing a templated Vector class for an assignment and I came across a few issues that I solved by Googling, but I still want to know why what I was doing was wrong. First issue is that I had:
template <typename T>
class Vector
{
...
template <typename T2>
Vector(const Vector<T2> &other);
}
template <typename T, T2>
Vector<T>::Vector(const Vector<T2> &other)
{
...
}
this was giving me an "unable to match function definition to an existing declaration" in VS11. I fixed it by putting the template definitions on separate lines:
template <typename T>
template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{
...
}
but I still don't know why this was needed. I know that the first definition is valid for functions/classes that use multiple templates in them, but why is it the case that the syntax changes when you mix a templated class with a templated member function?
My second question has to do with types inside of template classes. When writing the iterator I had functions such as:
template <typename T>
class Vector
{
...
class iterator
{
...
iterator &operator++(void);
}
}
template <typename T>
Vector<T>::iterator &Vector<T>::iterator::operator++(void)
{
...
}
which gave me "dependent name is not a type" and I later found out that I needed to add "typename" in front:
template <typename T>
typename Vector<T>::iterator &Vector<T>::iterator::operator++(void)
{
...
}
After Googling the warning number (which resulted in an error), I realized why the error exists, but it isn't too obvious why the compiler doesn't know that Vector<T>::iterator is a type. I mean, it has the definition of the class, so...
Anyway, thanks for clarifying these few things for me!
template <typename T>
template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{
Is also valid to be written as
template <typename T> template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{
You just need (?) to write it out as two sets, since they are after all two sets of parameters - first one is for the class, second one for the function.
typename for dependant types and related rules (this for template base class members and template for template member functions(?) ) have to do with something called "Two Phase Lookup". This is however badly implemented (as in not) on MSVC++, so it may not throw as many errors as a conforming implementation might.
More info - http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html
http://womble.decadent.org.uk/c++/template-faq.html#disambiguation
http://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates/