2016-08-16 40 views
6

Tiêu chuẩn C++ 14.8.2 $ 7 cho biết:Làm thế nào để thay thế hoạt động trong khấu trừ đối số mẫu?

Sự thay thế xảy ra trong tất cả các loại và biểu thức được sử dụng trong kiểu hàm và khai báo tham số mẫu. Các biểu thức bao gồm không chỉ các biểu thức liên tục như các biểu thức xuất hiện trong mảng giới hạn hoặc như các đối số mẫu nontype mà còn biểu thức chung (tức là các biểu thức không liên tục) bên trong sizeof, decltype và các ngữ cảnh khác cho phép các biểu thức không liên tục. Việc thay thế diễn ra theo thứ tự từ vựng và dừng lại khi gặp phải tình trạng khiến cho việc khấu trừ thất bại. [Lưu ý: Việc thay thế tương đương trong các đặc tả ngoại lệ chỉ được thực hiện khi đặc tả ngoại lệ được khởi tạo, tại thời điểm đó một chương trình bị hỏng nếu kết quả thay thế trong một loại hoặc biểu thức không hợp lệ. - cuối note]

Tiêu chuẩn cung cấp một ví dụ ở đây:

template <class T> struct A { using X = typename T::X; }; 
template <class T> typename T::X f(typename A<T>::X); 
template <class T> void f(...) { } 
template <class T> auto g(typename A<T>::X) -> typename T::X; 
template <class T> void g(...) { } 

void h() { 
    f<int>(0); // OK, substituting return type causes deduction to fail 
    g<int>(0); // error, substituting parameter type instantiates A<int> 
} 

Tại sao gọi g<int>(0) là một lỗi ở đây? Không phải kiểu kết quả trả về lỗi T::X gây ra sự cố thay thế? Sự khác biệt giữa chức năng mẫu fg là gì?

Trả lời

4

Các điểm chính là, trước hết,

Số tiền thu được thay theo thứ tự từ vựng và dừng lại khi một điều kiện gây khấu trừ thất bại được gặp

Và thứ hai, instantiation của A<int> 's định nghĩa gây ra một lỗi cứng, không phải là một sự thay thế thất bại, bởi vì đó là kết quả trong instantiating một cấu trúc không hình thành typename T::X (với T == int) bên ngoài bối cảnh ngay lập tức. [temp.deduct]/8: Các loại

Chỉ không hợp lệ và biểu thức trong bối cảnh trước mắt của các loại chức năng và các loại tham số mẫu của nó có thể gây ra một sự thất bại khấu trừ. [Note: Việc đánh giá các loại thay và các biểu thức có thể dẫn đến tác dụng phụ như các instantiation của lớp mẫu chuyên ngành và/hoặc chức năng template chuyên ngành, thế hệ của chức năng ngầm định nghĩa vv tác dụng phụ như vậy không nằm trong "bối cảnh ngay lập tức" và có thể dẫn đến chương trình bị lỗi. - cuối note]

Với các mẫu tại vấn đề, thay vào typename T::X trong các kết quả loại chức năng trong một thất bại khấu trừ (ví dụ: SFINAE); thay thế thành typename A<T>::X dẫn đến lỗi nghiêm trọng. Vì sự thay thế diễn ra theo thứ tự từ vựng, đối với template <class T> typename T::X f(typename A<T>::X);, nó thay thế thành typename T::X trước tiên, dẫn đến lỗi khấu trừ và không thay thế thêm. Đối với template <class T> auto g(typename A<T>::X) -> typename T::X;, mặt khác, nó thay thế thành typename A<T>::X đầu tiên, dẫn đến lỗi nghiêm trọng.

+0

Kiểu trả về là một phần của chữ ký hàm chứ không phải là tham số? – Barry

+0

@Barry Tôi nghĩ cả kiểu trả về và tham số đều được coi là một phần của chữ ký chức năng – Carousel

+0

@Barry Cả hai đều là một phần của chữ ký của mẫu chức năng, nhưng có lẽ tôi không nên sử dụng chữ ký ở đây. –

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