[英]Trouble passing a template function as an argument to another function in C++
問題的根源 - 加速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函數時,我的問題出現了。 我似乎無法得到正確的類型。
所以我的問題是,您是否可以將模板函數作為參數傳遞給另一個函數,如果是這樣,您是否必須在傳遞之前聲明所有類型? 或者編譯器可以從模板化函數在體內使用的方式推斷出類型?
為了演示我得到的錯誤,請注釋掉現有的外部參照函數標題,並取消注釋我正在嘗試使用的備用標題(正好在下面的通信行下面。)同時注釋標記為LINE 2和LINE 3的行並取消注釋LINE 4 ,它試圖使用參數find_words (默認為拆分 。)
感謝您的任何反饋!
這個問題的答案是:不。
您需要將'typedef Out'更改為back_inserter返回的類型,並且您需要將相同的類型提供給“= split <type_here>”。
back_inserter返回的類型由標准指定,因此您應該能夠在C ++庫引用中找到它。
您也可以嘗試將外部參照功能轉換為一個模板,該模板將函數模板作為參數(及其類型)。 我從來沒有嘗試過類似的東西,但不管功能如何,所以我不知道會帶來多少成功。 它可能是你想要的,也可能不是。
如果您使用的是c ++ 0x,那么您可以選擇更多可能更符合您需求的選項。
以下是一種解決方法。 您可以使用具有靜態函數的類
struct split
{
template <class Out>
static apply(const string& s, Out os) {
// include the body of your split function or call to an existing function
}
};
現在,使xref成為通用的
template <typename FIND_WORDS>
map<string, vector<int> > xref(istream& in, FIND_WORDS find_words = split())
{
// replace #2 and #3 by
find_words.apply(line, back_inserter(words));
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.