2015-04-23 17 views
6

Xét đoạn mã sau:C++ chức năng phân giải lựa chọn phiên bản templated qua chức năng đơn giản

#include <iostream> 

template<typename T> 
void f(T t) 
{ 
    (void)t; 
    std::cout << "templated f(T)\n"; 
} 

template<typename T> 
void entry(T t) 
{ 
    f(t); 
} 

void f(double d) 
{ 
    (void)d; 
    std::cout << "normal f(double)\n"; 
} 

int main() 
{ 
    double d = 0.0; 
    entry(d); 

    return 0; 
} 

Output:

templated f (T)

Tôi thấy ngạc nhiên này, bởi vì tôi nghĩ rằng các chức năng đồng bằng sẽ được lựa chọn trên bất kỳ phiên bản templated. Lý do tại sao điều này xảy ra?

Một điều tôi nhận thấy khi chơi xung quanh là: nếu tôi đặt các chức năng bình thường void f(double) trước templated void entry(T) chức năng mã sẽ gọi hàm bình thường, về cơ bản xuất ra:

f bình thường (đôi)

Vì vậy, câu hỏi khác của tôi: tại sao thứ tự quan trọng trong ví dụ cụ thể này?

Trả lời

7

f là tên phụ thuộc, vì nó phụ thuộc vào t loại của nó là thông số mẫu. Các quy tắc tra cứu tên cho tên phụ thuộc được đưa ra trong [temp.dep.res]/1:

Trong việc giải quyết các tên thuộc, tên từ các nguồn sau đây được coi là:

  • khai báo rằng có thể nhìn thấy ở điểm định nghĩa của mẫu.
  • Tuyên bố từ không gian tên được liên kết với các loại đối số hàm cả hai từ ngữ cảnh tức thời (14.6.4.1) và từ ngữ cảnh định nghĩa.

Nói cách khác, thông thường tên tra cứu bên trong một mẫu duy nhất tìm thấy tên đã được khai báo trước khi mẫu định nghĩa (mà không phải là đáng ngạc nhiên, vì nó giống như cho không mẫu). Điểm bullet thứ hai cho phép các tên được khai báo sau khi định nghĩa mẫu được tìm thấy, nhưng chỉ khi ADL xảy ra. Điều này sẽ không xảy ra khi đối số là loại cơ bản như double.

+0

Ok, ... tuy nhiên tôi nhận thấy rằng tra cứu bên trong một mẫu sẽ tìm thấy một tên ngay cả * sau * khai báo mẫu nếu nó là mẫu khác, thậm chí là chuyên môn hóa mẫu với kiểu cơ bản như 'double'. Tôi đã kiểm tra điều này bằng cách thay đổi hàm bình thường thành một khuôn mẫu chuyên biệt: 'template <> void f (double)'. Kết quả là mẫu chuyên biệt được gọi, mặc dù nó đã qua điểm khai báo của mã gọi. – Edenbridge

+0

@Edenbridge Tra cứu tên luôn tìm mẫu chính. Việc khớp các chuyên môn xảy ra sau khi tra cứu tên và có một quy tắc khác: nếu mẫu được khởi tạo trước khi chuyên môn hóa một phần phù hợp nhất được khai báo, thì chương trình không đúng chuẩn mà không cần chẩn đoán.Nếu bạn có thêm bất kỳ thắc mắc nào, vui lòng đăng câu hỏi riêng. – Brian

0

Quá tải cho f(double) không hiển thị đối với trình biên dịch khi mẫu entry(T) được phân tích cú pháp. Do đó, nó sẽ không tham gia vào độ phân giải quá tải khi mẫu entry(T) được khởi tạo. Đây chỉ là một quy tắc tối nghĩa khi nói đến việc giải quyết tình trạng quá tải trong một bối cảnh instantiation mẫu. Để một tình trạng quá tải được xem xét, nó phải đã được nhìn thấy trong đơn vị dịch trước khi định nghĩa mẫu được phân tích cú pháp.

Các vấn đề liên quan