【发布时间】:2010-04-23 16:35:55
【问题描述】:
问题根源-加速C++,问题8-5
我编写了一个小程序,它检查字符串输入的行,并计算一个单词在给定行上出现的次数。下面的代码实现了这一点:
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <cctype>
#include <iterator>
using std::vector; using std::string;
using std::cin; using std::cout;
using std::endl; using std::getline;
using std::istream; using std::string;
using std::list; using std::map;
using std::isspace; using std::ostream_iterator;
using std::allocator;
inline void keep_window_open()
{
cin.clear();
cout << "Please enter EOF to exit\n";
char ch;
cin >> ch;
return;
}
template <class Out>
void split(const string& s, Out os)
{
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;
// invariant: we have processed characters `['original value of `i', `i)'
while (i != s.size()) {
// ignore leading blanks
// invariant: characters in range `['original `i', current `i)' are all spaces
while (i != s.size() && isspace(s[i]))
++i;
// find end of next word
string_size j = i;
// invariant: none of the characters in range `['original `j', current `j)' is a space
while (j != s.size() && !isspace(s[j]))
++j;
// if we found some nonwhitespace characters
if (i != j) {
// copy from `s' starting at `i' and taking `j' `\-' `i' chars
*os++ = (s.substr(i, j - i));
i = j;
}
}
}
// find all the lines that refer to each word in the input
map<string, vector<int> > xref(istream& in) // works
// now try to pass the template function as an argument to function - what do i put for templated type?
//map<string, vector<int> > xref(istream& in, void find_words(vector<string, typedef Out) = split) #LINE 1#
{
string line;
int line_number = 0;
map<string, vector<int> > ret;
// read the next line
while (getline(in, line)) {
++line_number;
// break the input line into words
vector<string> words; // works // #LINE 2#
split(line, back_inserter(words)); // #LINE 3#
//find_words(line, back_inserter(words)); // #LINE 4# attempting to use find_words as an argument to function
// remember that each word occurs on the current line
for (vector<string>::const_iterator it = words.begin();
it != words.end(); ++it)
ret[*it].push_back(line_number);
}
return ret;
}
int main()
{
cout << endl << "Enter lines of text, followed by EOF (^Z):" << endl;
// call `xref' using `split' by default
map<string, vector<int> > ret = xref(cin);
// write the results
for (map<string, vector<int> >::const_iterator it = ret.begin();
it != ret.end(); ++it) {
// write the word
cout << it->first << " occurs on line(s): ";
// followed by one or more line numbers
vector<int>::const_iterator line_it = it->second.begin();
cout << *line_it; // write the first line number
++line_it;
// write the rest of the line numbers, if any
while (line_it != it->second.end()) {
cout << ", " << *line_it;
++line_it;
}
// write a new line to separate each word from the next
cout << endl;
}
keep_window_open();
return 0;
}
如您所见,split函数是一个模板函数,可以根据需要处理各种类型的输出迭代器。
当我尝试通过传入模板化的 split 函数作为参数来概括 xref 函数时,我的问题就出现了。我似乎无法正确输入类型。
所以我的问题是,你可以将模板函数作为参数传递给另一个函数吗?如果可以,是否必须在传递之前声明所有类型?或者编译器可以根据模板化函数在主体中的使用方式来推断类型吗?
为了演示我得到的错误,注释掉现有的 xref 函数标题,并取消注释我正在尝试工作的备用标题(就在下面的注释行下方。)同时注释这些行标记了第 2 行和第 3 行并取消注释第 4 行,它正在尝试使用参数 find_words(默认为 split。)
感谢您的任何反馈!
【问题讨论】:
-
请尝试发布 minimal 示例代码。
-
此外,C++ 中没有“模板函数”之类的东西。这是一个“功能模板”。
-
我认为一个简单的
using namespace std;就足够了:-) -
并发布不起作用的代码 - 不要让我们自己编辑它。我打算将您的代码编辑为基本问题,但我真的不知道您的问题是什么,或者如何转换您的代码以说明问题。
-
积分。我认为发布一个完整的、有效的程序将最好地展示我正在尝试做的事情。