Bên trong C++ foo template function(), một cuộc gọi đến :: bar (TT *) cung cấp cho các lỗi sau đây theo gcc 4.4.3:Trong hàm mẫu C++, tại sao gọi hàm phụ thuộc cho lỗi "không khai báo"?
g++ -o hello.o -c -g hello.cpp
hello.cpp: In function 'void foo(std::vector<TT*, std::allocator<TT*> >&)':
hello.cpp:8: error: '::bar' has not been declared
Dưới đây là mã vi phạm:
// hello.cpp
#include <vector>
template<typename TT> void foo(std::vector<TT*> &vec)
{
TT *tt;
::bar(tt);
vec.push_back(tt);
}
class Blah
{
};
void bar(Blah *&)
{
}
int main(int argc, char *argv[])
{
std::vector<Blah*> vec;
foo(vec);
return 0;
}
C++ phân biệt giữa các biểu tượng phụ thuộc vào tham số mẫu (TT, ở đây) và các biểu tượng độc lập và có thể được đánh giá ngay lập tức.
Rõ ràng, trình biên dịch nghĩ rằng lời gọi :: bar (TT *) của tôi là độc lập và cố gắng giải quyết ngay lập tức. Cũng như rõ ràng, hàm đó gọi là phụ thuộc vào TT vì hàm gọi có tham số kiểu TT *, do đó trình biên dịch phải chờ cho đến khi foo (vec) instantiation giải quyết :: bar (TT *).
Đây có phải là lỗi của gcc hoặc tôi thiếu điều gì đó tinh tế về mẫu C++ không?
EDIT: đây là ví dụ hơi phức tạp hơn với hai phiên bản :: bar() để làm rõ rằng thứ tự khai báo không phải là vấn đề với sự cố của tôi. Khi phân tích cú pháp mẫu, trình biên dịch có không cách biết nếu chính() xuống dưới đây sẽ khởi tạo chức năng mẫu với TT = Blah hoặc với TT = Argh. Do đó trình biên dịch không nên đưa ra lỗi cho đến khi
dòng 35
dòng 28 sớm nhất (nếu có). Nhưng lỗi được đưa ra cho
dòng 8
dòng 16.
EDIT # 2: cải thiện ví dụ này.
EDIT # 3: đã thêm sửa đổi cho ví dụ này để làm cho nó hoạt động như mong muốn. Thanh (tt) bây giờ đề cập chính xác đến thanh (Blah *). Lý do được đưa ra dưới đây. (Cảm ơn mọi người).
// hello.cpp
#include <vector>
class XX {};
void bar(XX*) {}
class CC {
public:
void bar();
void bar(int *);
void bar(float *);
template<typename TT> static void foo(std::vector<TT*> &vec);
};
template<typename TT>
void CC::foo(std::vector<TT*> &vec) {
using ::bar;
TT *tt;
bar(tt);
vec.push_back(tt);
}
class Argh {};
void bar(Argh *&aa) { aa = new Argh; }
class Blah {};
void bar(Blah *&bb) { bb = new Blah; }
int main(int argc, char *argv[]) {
std::vector<Blah*> vec;
CC::foo(vec);
return 0;
}
lỗi nói ":: thanh" không được khai báo không giống như "nguyên mẫu không khớp" ... có thể thanh thực sự không được khai báo? Đây là phỏng đoán –
"Chỉ cần rõ ràng, hàm gọi đó phụ thuộc vào TT vì hàm gọi có tham số kiểu TT *, do đó trình biên dịch phải chờ cho đến khi diễn giải foo (vec) :: thanh (TT *) ". Sai rồi. Các tên ":: bar" và "bar" không phụ thuộc. Có một quy tắc đặc biệt để làm cho các tên không phụ thuộc khác phụ thuộc vào chúng khi chúng được sử dụng như là một chú thích, đó là dấu ngoặc kép @Chris văn bản và chỉ áp dụng cho các tên không đủ tiêu chuẩn. Những gì cần phải được thực hiện tại instantiation anyway là quá tải độ phân giải trên các tuyên bố được tìm thấy [s] với các đối số (phụ thuộc) nhất định. –
Tôi đã đề cập điều này bên dưới, nhưng điều này dường như không đồng ý với bạn: Stroustrup TC++ PL Sp Ed, Phần C.13.8.1, Tên phụ thuộc: "Về cơ bản, tên của hàm được gọi là phụ thuộc nếu nó rõ ràng là phụ thuộc nhìn vào các đối số của nó hoặc tại các tham số chính thức của nó ". Theo tiêu chí đó, ':: bar' là" rõ ràng là phụ thuộc ". –