我正在閱讀一本書(Accelerated C++)並從那本試圖通過自己學習C++的書中鍛鍊身體。模板,爲什麼用這種方式調用模板函數不起作用?
現在我想明白爲什麼下面這段代碼不工作:
// analysis.cpp
void write_analysis(ostream& out, const string& name,
double analysis(const vector<Student_info>&),
const vector<Student_info>& did,
const vector<Student_info>& didnt)
{
out << name << ":median(did) = " << analysis(did) <<
", median(didnt)=" << analysis(didnt) << endl;
}
template <double F(Student_info&)>
double generic_analysis(const vector<Student_info>& students)
{
vector<double> grades;
transform(students.begin(), students.end(),
back_inserter(grades), F);
return median(grades);
}
template<> double generic_analysis<grade_aux>(const vector<Student_info>& students);
double median_analysis(const vector<Student_info>& students)
{
return generic_analysis<grade_aux>(students);
// if not using template function, the code will be
// as following
// vector<double> grades;
// transform(students.begin(), students.end(),
// back_inserter(grades), grade_aux);
// return median(grades);
}
analysis.cpp
// analysis.h
template <double F(const Student_info&)>
double generic_analysis(const std::vector<Student_info>&);
void write_analysis(std::ostream&, const std::string&,
double analysis(const std::vector<Student_info>&),
const std::vector<Student_info>&,
const std::vector<Student_info>&);
double grade_aux(const Student_info&);
double median_analysis(const std::vector<Student_info>&);
analysis.h
// main.cpp
int main()
{
// students who did and didn't do all their homework
vector<Student_info> did, didnt;
// read the student records and partition them
Student_info student;
while (read(cin, student)) {
did.push_back(student);
}
// do the analyses
write_analysis(cout, "median", median_analysis, did, didnt);
return 0;
}
爲主。 cpp
// grade.cpp
// compute a student's overall grade from midterm and final exam grades
// and homework grade
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
double grade_aux(const Student_info& s)
{
try {
return grade(s);
} catch (domain_error) {
return grade(s.midterm, s.final, 0);
}
}
grade.cpp
和錯誤消息是:
g++ -Wall *.cpp -o main /tmp/ccbXbVcV.o: In function
median_analysis(std::vector<Student_info, std::allocator<Student_info> > const&)': analysis.cpp:(.text+0x91): undefined reference to
double generic_analysis<&(grade_aux(Student_info const&))>(std::vector > const&)' collect2: ld returned 1 exit status
同時,當我把generic_analysis代碼聲明並定義頭文件, 它會在裏面工作。請有人解釋爲什麼?
編輯: 當刪除行:
template<> double generic_analysis<average_grade>(const vector<Student_info>& students);
我:
g++ -Wall *.cpp -o main /tmp/cc3VhXKU.o: In function
median_analysis(std::vector<Student_info, std::allocator<Student_info> > const&)': analysis.cpp:(.text+0x91): undefined reference to
double generic_analysis<&(grade_aux(Student_info const&))>(std::vector > const&)' collect2: ld returned 1 exit status
所以好像我需要一個Explicit instantiation
。然後我添加了下面一行:
template double generic_analysis<grade_aux>(const vector<Student_info>&);
現在的錯誤信息是:
g++ -Wall *.cpp -o main
analysis.cpp: In instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’:
analysis.cpp:26:72: instantiated from here analysis.cpp:26:72: error: explicit instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’ but no definition available [-fpermissive] analysis.cpp: In instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’:
analysis.cpp:26:72: instantiated from here analysis.cpp:26:72: error: explicit instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’ but no definition available [-fpermissive] analysis.cpp: In instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’:
analysis.cpp:26:72: instantiated from here analysis.cpp:26:72: error: explicit instantiation of ‘double generic_analysis(const std::vector&) [with double (* F)(const Student_info&) = grade_aux]’ but no definition available [-fpermissive]
明確地實例化模板可能比結果值得更麻煩,因爲'generic_analysis'和'grade_aux'生活在不同的TU中,試圖用後者實例化前者肯定是痛苦的。我推薦你將類似'generic_analysis'這樣的函數模板的定義放在頭文件中,就像習慣使用模板一樣。 –