Dependent Scope and Nested Templates

Dependent scope and nested templates

The C++ grammar is horrendous, and as such it is not possible, when given a template class, to know whether the ::node you refer to is a variable/constant or a type.

The Standard therefore mandates that you use typename before types to remove this ambiguity, and treats all other usages as if it was a variable.

Thus

template <typename T, int degree>
typename btree<T,degree>::node* btree<T,degree>::findLead(T const& value)
^~~~~~~~

is the correct signature for the definition.

Nested templates with dependent scope

The compiler told you exactly what to do. Write typename before ptrModel<std::vector<Data> >::Type, like so:

 typedef typename ptrModel<std::vector<Data> >::Type Type;

The reason for this requirement is that the compiler doesn't at this point know whether ptrModel<std::vector<Data> >::Type describes a member variable or a nested type. It can't even figure that out by looking at the definition of ptrModel because there might be a specialization of ptrModel for std::vector<Data> somewhere else in the program that it hasn't gotten to yet which changes which of these things ::Type refers to. So you need to tell it explicitly.

The name ptrModel<std::vector<Data> >::Type has a "dependent scope" because it is in a scope that depends on the instantiation of a template.

typedef typename and Dependent scope

Your Ideone sample fixed:

#include <iostream>

#include <vector>
#include <iterator>

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class PtrVector
{
private:
typedef std::vector<_Tp, _Alloc> VectrorT;
typedef typename std::vector<_Tp, _Alloc>::const_iterator VTConstIter;
// ^^^^^^^^ ^^^^^^^^^^^^^^^^

public:

typename std::vector<_Tp, _Alloc>::const_iterator test(){}
// ^^^^^^^^ ^^^^^^^^^^^^^^^^
VTConstIter test2(){}

};

int main() {
return 0;
}

As for your comments, see these variants also:

// ...
typedef typename VectrorT::const_iterator VTConstIter; // also works
// ...
typename VectrorT::const_iterator test(){} // also works
// ...

I hope that clarifies abit further what's going on in the compilers guts.

need ‘typename’ before ‘..’ because ‘..’ is a dependent scope

There is no member called dataType, I assume the return type should be just the template dataType:

template <typename dataType>
dataType Node<dataType>::getData() const {
return nodeData;
}

The compiler message is misleading in this case as it doesn't find proper definition, it assumes the dataType refers to the template argument.

Is a local class dependent if declared within a function template?

According to my understanding (and the current wording of the standard), C in your example is not dependent. Neither is A<C>::Type, so the typename is not required.

There is a fundamental difference between nested classes of class templates and local classes in function templates: The latter cannot be specialized, thus any reference to a local class inside a function template is uniform. That is, in every specialization of f, C refers to the class C that is defined in this function template f. That is not the case with class templates as you can indeed explicitly specialize members on their own (as covered in [temp.expl.spec]
/(1.6)):

template <typename T>
class A { class C{}; };

template <>
class A<int>::C { int i; };

However:

A type is dependent if it is

  • a compound type constructed from any dependent type,

So if the definition was done as in dyp's example, C would be dependent as it is constructed from T.

There are unclarities in the standards wording that are being discussed in the comment section, e.g. about definitions of member functions that depend on T and how that transposes to the classes dependency.

dependent scope; need typename in front;

The compiler says

my_vector.h:21:2: error: need ‘typename’ before
‘std::vector::iterator’ because ‘std::vector’ is a
dependent scope

So you need to write

typename vector< a_type >::iterator vec1_pre = vec1.begin();
typename vector< a_type >::iterator vec1_pos = vec1.begin();

See Where and why do I have to put the "template" and "typename" keywords? for the reasons behind it.

One last remark: In C++11 you can use auto and don't have to think anymore:

auto vec1_pre = vec1.begin();
auto vec1_pos = vec1.begin();

C++ Non-Template Used as Template - Nested Template Classes

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 Topics



Leave a reply



Submit