Reputation: 187
template <class T>
class Node {
private:
T m_value;
//Node* m_ptr; //(1)
//Node<T>* m_ptr; //(2)
};
Can someone explain what is the difference between the above two statements (1) and (2)? Both statements seem to compile, but I can't seem to find what the ISO C++ says about them.
Upvotes: 9
Views: 596
Reputation: 311048
According to the C++ Standard (14.6.1 Locally declared names)
3 The injected-class-name of a class template or class template specialization can be used either as a template-name or a type-name wherever it is in scope. [ Example:
template <class T> struct Base {
Base* p;
};
template <class T> struct Derived: public Base<T> {
typename Derived::Base* p; // meaning Derived::Base<T>
};
template<class T, template<class> class U = T::template Base> struct Third { };
Third<Base<int> > t; // OK: default argument uses injected-class-name as a template
— end example ]
Thus these data member declarations
Node* m_ptr; //(1)
Node<T>* m_ptr; //(2)
are equivalent because the injected class name Node
is used in the scope of the class definition.
Upvotes: 9
Reputation: 8598
They are the same thing, because you declare the pointer inside the template, thus when you create an instance of Node
the compiler knows what T
is. You don't have to specify the type for a template if it can be deduced, e.g. from argument types, or in this case from the template instance the pointer belongs to.
template <class T>
class Node {
public:
T m_value;
Node* m_ptr; //(1)
//Node<T>* m_ptr; //(2)
};
int main()
{
Node<float> test;
test.m_ptr = new Node<float>{}; // valid
test.m_ptr = new Node<bool>{}; // invalid - triggers compiler error
auto val = test.m_ptr->m_value; // val will be of float type
}
Upvotes: 10
Reputation: 1
They are "the same"
I think that's what it is happening is, in the case of
Node* m_ptr_n
The compiler makes the type match the class type.
In the case of
Node < T>* m_ptr
What it's created is a pointer to a class witch template matches with the "T" type.
If you want to get an int instance that points to a float instance what you can do is pass both types to the template.
template <class T1, class T2, class T3>
class Node {
public:
T1 m_value;
// Node* m_ptr_n; //(1)
Node<T2, T3>* m_ptr; //(2)
};
Upvotes: 0