Tôi đã đọc về các hàm mẫu và bị lẫn lộn bởi vấn đề này:
#include <iostream>
void f(int) {
std::cout << "f(int)\n";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << " ";
f(val);
}
void f(double) {
std::cout << "f(double)\n";
}
template void g<double>(double);
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // d f(int), this is surprising
g(1); // i f(int)
}
Kết quả là như nhau nếu tôi không viết template void g<double>(double);
.
Tôi nghĩ rằng g<double>
nên được instantiated sau f(double)
, và do đó các cuộc gọi đến f
trong g
nên gọi f(double)
. Đáng ngạc nhiên, nó vẫn gọi f(int)
trong g<double>
. Bất cứ ai có thể giúp tôi hiểu điều này?
Sau khi đọc câu trả lời, tôi nhận ra sự nhầm lẫn của mình thực sự là gì.
Dưới đây là một ví dụ cập nhật. Nó hầu như không thay đổi ngoại trừ việc tôi đã thêm một chuyên ngành cho g<double>
:
#include <iostream>
void f(int){cout << "f(int)" << endl;}
template<typename T>
void g(T val)
{
cout << typeid(val).name() << " ";
f(val);
}
void f(double){cout << "f(double)" << endl;}
//Now use user specialization to replace
//template void g<double>(double);
template<>
void g<double>(double val)
{
cout << typeid(val).name() << " ";
f(val);
}
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // now d f(double)
g(1); // i f(int)
}
Với chuyên môn hóa người dùng, g(1.0)
hành xử như tôi mong đợi.
Trình biên dịch không nên tự động thực hiện việc khởi tạo tương tự này cho g<double>
cùng một vị trí (hoặc thậm chí sau đó main()
, như được mô tả trong phần 26.3.3 của Ngôn ngữ lập trình C ++ , phiên bản thứ 4)?
g(1)
,i f(int)
cho tôi. Bạn đã viếtd f(double)
. Đây có phải là một lỗi đánh máy?