What is going on here?

I wrote a function reverseVector() used in the program shown below:
There is no code...
The program I meant to post earlier is shown below. By the way, this version works perfectly! My question follows after.


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
#include <iostream>
#include <vector>
using namespace std; 


template<class elemType>
void reverseVector(vector<elemType>& list);


int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    vector<int> vec(arr, arr + sizeof(arr)/sizeof(int));
    
    reverseVector(vec);
    
    for (vector<int>::iterator iter = vec.begin(); iter != vec.end(); iter++)
        cout<<" "<<*iter;
    
    cout<<endl<<endl;
       
   	// wait until user is ready before terminating program
	system("PAUSE");
	return 0; 
}

 

template<class elemType>
void reverseVector(vector<elemType>& list)
{
    int i;
    elemType temp;
    vector<int>::iterator iter1 = list.begin();
    vector<int>::reverse_iterator iter2 = list.rbegin();
	
    if (list.size() == 1)
	return;      
    else if (list.size() == 2)
    {
	temp = *iter1;
	*iter1 = *iter2;
	*iter2 = temp;
    }
    else 
	for (i = 0; i < list.size()/2; i++)
	{
	    temp = *iter1;
	    *iter1 = *iter2;
	    *iter2 = temp;
	    iter1++;
	    iter2++;
	}		    	
}



I initially used elemType (as expected) for the class parameters in declaring the iterators in lines 34 and 35 as shown below:

1
2
vector<elemType>::iterator iter1 = list.begin();
 vector<elemType>::reverse_iterator iter2 = list.rbegin();


But I got a whole bunch of compiler errors, the log of which I show below:

Compiler: Default compiler
Executing  g++.exe...
g++.exe "C:\Users\Kolly\Desktop\DS4-4.cpp" -o "C:\Users\Kolly\Desktop\DS4-4.exe"    -I"C:\Dev-Cpp\lib\gcc\mingw32\3.4.2\include"  -I"C:\Dev-Cpp\include\c++\3.4.2\backward"  -I"C:\Dev-Cpp\include\c++\3.4.2\mingw32"  -I"C:\Dev-Cpp\include\c++\3.4.2"  -I"C:\Dev-Cpp\include"   -L"C:\Dev-Cpp\lib" 
C:\Users\Kolly\Desktop\DS4-4.cpp: In function `void reverseVector(std::vector<elemType, std::allocator<_CharT> >&)':
C:\Users\Kolly\Desktop\DS4-4.cpp:34: error: expected `;' before "iter1"
C:\Users\Kolly\Desktop\DS4-4.cpp:35: error: expected `;' before "iter2"
C:\Users\Kolly\Desktop\DS4-4.cpp:41: error: `iter1' undeclared (first use this function)
C:\Users\Kolly\Desktop\DS4-4.cpp:41: error: (Each undeclared identifier is reported only once for each function it appears in.)
C:\Users\Kolly\Desktop\DS4-4.cpp:42: error: `iter2' undeclared (first use this function)

C:\Users\Kolly\Desktop\DS4-4.cpp: In function `void reverseVector(std::vector<elemType, std::allocator<_CharT> >&) [with elemType = int]':
C:\Users\Kolly\Desktop\DS4-4.cpp:15:   instantiated from here
C:\Users\Kolly\Desktop\DS4-4.cpp:34: error: dependent-name ` std::vector<elemType,std::allocator<_CharT> >::iterator' is parsed as a non-type, but instantiation yields a type
C:\Users\Kolly\Desktop\DS4-4.cpp:34: note: say `typename  std::vector<elemType,std::allocator<_CharT> >::iterator' if a type is meant
C:\Users\Kolly\Desktop\DS4-4.cpp:35: error: dependent-name ` std::vector<elemType,std::allocator<_CharT> >::reverse_iterator' is parsed as a non-type, but instantiation yields a type
C:\Users\Kolly\Desktop\DS4-4.cpp:35: note: say `typename  std::vector<elemType,std::allocator<_CharT> >::reverse_iterator' if a type is meant

Execution terminated


Why is it that I could not use elemType as the class parameter for the iterator declarations in lines 34 and 35? At least, that is what was passed into the function.
Thx for the link you sent. I checked it out but, unfortunately, do not see how it addresses my problem here. I am not using any derived class in my code as the material on there seems to deal with.
In a template that we write, there are two kinds of names that could be used - dependent names and non- dependent names. A dependent name is a name that depends on a template parameter; a non- dependent name has the same meaning irrespective of what the template parameters are. For example:

1
2
3
4
5
template< typename T > void foo( T& x, int value )
{
    ++ T::static_member_variable ; // 'static_member_variable' is a dependent name
    ++value ; // 'value' is a non- dependent name
}


What a dependent name refers to could be something different for each different instantiation of the template. As a consequence, C++ templates are subject to "two-phase name lookup". When a template is initially parsed (before any instantiation takes place) the compiler looks up the non-dependent names. When a particular instantiation of the template takes place, the template parameters are known by then, and the compiler looks up dependent names.

During the first phase, the parser needs to know if a dependent name is the name of a type or the name of a non-type. By default, a dependent name is assumed to be the name of a non-type. The typename keyword before a dependent name disambiguates it to be the name of a type.

1
2
3
4
5
6
7
8
template < typename T > std::vector<T> reverse( std::vector<T> seq )
{
    // vector<T>::iterator and std::vector<T>::reverse_iterator are dependant names
    // disambiguate by qualifying them with typename. tell the parser that these are names of types 
    typename std::vector<T>::iterator iter1 = seq.begin() ;
    typename std::vector<T>::reverse_iterator iter2 = seq.rbegin() ;
    // ...
}


With C++11, we can use auto and let the compiler figure out the details.

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
#include <iostream>
#include <vector>
#include <algorithm>

template < typename T > std::vector<T> reverse_vector( std::vector<T> seq )
{
    auto iter1 = seq.begin() ; // here auto is deduced to be decltype( seq.begin() )
    auto iter2 = seq.rbegin() ; 

    while( iter1 < iter2.base() )
    {
        using std::swap ;
        swap( *iter1, *iter2 ) ;
        ++iter1 ;
        ++iter2 ;
    }

    return seq ;
}

int main()
{
    const std::vector<std::string> vec { "zero", "one", "two", "three", "four" } ;
    
    for( const auto& str : reverse_vector(vec) ) std::cout << str << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/72575f4f97df1bd0
note: say `typename std::vector<elemType,std::allocator<_CharT> >::reverse_iterator' if a type is meant


(B<T>::Pqr y;)Unfortunately this doesn’t work either because those names (are you ready? are you sitting down?) are not necessarily types.(...) the compiler cannot assume that B<T>::Xyz is a type until it knows T. The solution is to give the compiler a hint via the typename keyword:



Also http://en.cppreference.com/w/cpp/language/dependent_name (see «The typename disambiguator for dependent names»)
@JLBorges:
Wow! I really appreciate your in-depth and insightful explanation. This problem I ran into has led me to knowing more about compiler type resolution vis-a-vis template declarations and definitions. All I did to make my program work with the initial elemType template parameters was to precede lines 34 and 35 with the keyword typename.

Thx ne555 for the link.
Topic archived. No new replies allowed.