习题16.12原答案g++下编译出错的解决
习题16.12:
Exercise 16.12:
编写一个函数模板,接受表示未知类型迭代器的一对值,找出在序列中出现得最频繁的值。
在做C++Primer 16.12的时候原答案在g++上编译老是出错(我改了原答案的部分变量函数名):
16_12.cpp: In function ‘typename Iter::value_type findMost(Iter, Iter)’:
16_12.cpp:18: error: expected ‘;’ before ‘newFirst’
16_12.cpp:19: error: expected ‘;’ before ‘newLast’
16_12.cpp:21: error: ‘newFirst’ was not declared in this scope
16_12.cpp:22: error: ‘sort’ is not a member of ‘std’
16_12.cpp:22: error: ‘newLast’ was not declared in this scope
16_12.cpp:26: error: expected ‘;’ before ‘preIter’
16_12.cpp:27: error: expected ‘;’ before ‘maxOccuElemIt’
16_12.cpp:30: error: ‘preIter’ was not declared in this scope
16_12.cpp:35: error: ‘maxOccuElemIt’ was not declared in this scope
16_12.cpp:40: error: ‘preIter’ was not declared in this scope
16_12.cpp:46: error: ‘maxOccuElemIt’ was not declared in this scope
16_12.cpp:46: error: ‘preIter’ was not declared in this scope
16_12.cpp:48: error: ‘maxOccuElemIt’ was not declared in this scope
16_12.cpp: In function ‘typename Iter::value_type findMost(Iter, Iter) [with Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]’:
16_12.cpp:57: instantiated from here
16_12.cpp:18: error: dependent-name ‘std::VecType::iterator’ is parsed as a non-type, but instantiation yields a type
16_12.cpp:18: note: say ‘typename std::VecType::iterator’ if a type is meant
16_12.cpp:19: error: dependent-name ‘std::VecType::iterator’ is parsed as a non-type, but instantiation yields a type
16_12.cpp:19: note: say ‘typename std::VecType::iterator’ if a type is meant
16_12.cpp:26: error: dependent-name ‘std::VecType::iterator’ is parsed as a non-type, but instantiation yields a type
16_12.cpp:26: note: say ‘typename std::VecType::iterator’ if a type is meant
16_12.cpp:27: error: dependent-name ‘std::VecType::iterator’ is parsed as a non-type, but instantiation yields a type
16_12.cpp:27: note: say ‘typename std::VecType::iterator’ if a type is meant
后来反复查看code,以及从网上查找,终于找到原因,在定义完新的类型别名后:
typedef std::vector<typename Iter::value_type> VecType;
原答案在使用容器迭代器的时候直接使用双冒号调用了:
VecType::iterator newFirst=vec.begin();
VecType::iterator newLast=vec.end();
...
VecType::iterator preIter=newFirst;
VecType::iterator maxOccuElemIt=newFirst;
但是正像这题想要考察的一样,如果要在函数模板内部使用内置定义类型,必须显示地告诉编译器我们正在使用的名字指的是一个类型。因为编译器(以及程序的读者)不能通过检查得知,由类型形参定义的名字何时是一个类型何时是一个值。所以这里应该加上typename,改写为:
typename VecType::iterator newFirst=vec.begin();
typename VecType::iterator newLast=vec.end();
...
typename VecType::iterator preIter=newFirst;
typename VecType::iterator maxOccuElemIt=newFirst;
最后在std::sort(newFirst,newLast);
这句也有报错,说sort不是std的成员,只需把std去掉,加上头文件#include\<\algorithm>就可以了。最后贴上在g++编译通过的code:
1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4 //#include <iterator>
5 using namespace std;
6
7 template <typename Iter> typename Iter::value_type findMost(Iter first,Iter last)
8 {
9 std::size_t amount=0;
10 Iter start=first;
11 while(start != last)
12 {
13 amount++;
14 start++;
15 }
16 typedef std::vector<typename Iter::value_type> VecType;
17
18 VecType vec(amount);
19
20 typename VecType::iterator newFirst=vec.begin();
21 typename VecType::iterator newLast=vec.end();
22
23 std::uninitialized_copy(first,last,newFirst);
24 sort(newFirst,newLast);
25
26 size_t maxOccu=0,occu=0;
27
28 typename VecType::iterator preIter=newFirst;
29 typename VecType::iterator maxOccuElemIt=newFirst;
30 while(newFirst != newLast)
31 {
32 if(*newFirst != *preIter)
33 {
34 if(occu>maxOccu)
35 {
36 maxOccu=occu;
37 maxOccuElemIt=preIter;
38 }
39 occu=0;
40 }
41 ++occu;
42 preIter=newFirst;
43 ++newFirst;
44 }
45 if(occu>maxOccu)
46 {
47 maxOccu=occu;
48 maxOccuElemIt=preIter;
49 }
50 return *maxOccuElemIt;
51 }
52
53 int main()
54 {
55 int ia[]={1,5,1,2,5,2,7,9,5,6,4,6,8,1,5,6,8,3,9,8,7,5,6,1,2,4,5,6,8};
56 int cnt=sizeof(ia)/sizeof(int);
57 cout<<"cnt:"<<cnt<<endl;
58 vector<int> ivec(ia,ia+cnt);
59 cout<<"most find element is:"<<findMost(ivec.begin(),ivec.end())<<endl;
60 return 0;
61 }