2013-03-06 29 views
11

Với "không phụ thuộc" ở đây tôi có nghĩa là "không phụ thuộc vào bất kỳ đối số mẫu nào khác của mẫu chức năng cụ thể đó".Các đối số mẫu mặc định không phụ thuộc của các mẫu chức năng có cho phép SFINAE không?

Khi trả lời this question, tôi nghĩ tôi đã tìm được câu trả lời, nhưng theo @Johannes (trong phần nhận xét cho câu trả lời của tôi), tôi hiểu sai tiêu chuẩn ở đây. Lấy ví dụ đơn giản sau:

#include <type_traits> 

template<class T> 
struct X{ 
    template<class U = typename T::type> 
    static void foo(int){} 
    static void foo(...){} 
}; 

int main(){ 
    X<std::enable_if<false>>::foo(0); 
} 

(Live version.)

Có bất kỳ sự đảm bảo rằng các biên dịch trên? GCC và Clang không đồng ý ở đây, như có thể thấy trong phiên bản trực tiếp khi chuyển đổi giữa chúng. Điều thú vị là, mặc dù, sau đây được chấp nhận bởi GCC:

#include <type_traits> 

template<class T> 
struct X{ 
    template<bool = T::f()> 
    static void foo(int){} 
    static void foo(...){} 
}; 

struct Y{ 
    static bool f(){ return true; } 
}; 

int main(){ 
    X<Y>::foo(0); 
} 

(Live version.)

Đoạn thứ hai sẽ chỉ in foo(int) nếu T chứa một constexpr chức năng tĩnh f. Một lần nữa, thật thú vị, nếu bạn xóa hoàn toàn f từ Y (hoặc vượt qua, giả sử, int thay thế), GCC khiếu nại về thành viên bị thiếu, cho biết rằng nó không cho phép SFINAE - mâu thuẫn với quan sát trước đó. Clang có tất cả các biến thể và áp dụng SFINAE, và tôi tự hỏi nếu đó là những gì được đảm bảo bởi tiêu chuẩn.

(FWIW, MSVC với tháng mười một CTP thường đồng ý với Clang, nhưng tai nạn trên đoạn thứ hai nếu chức năng có mặt, có khả năng bởi vì họ không có constexpr. Tôi đã gửi một báo cáo lỗi here.)

Trả lời

3

Tôi nghĩ rằng mã trong câu hỏi là không chính xác, như khi mẫu lớp được khởi tạo, tất cả các khai báo thành viên được khởi tạo, ngoại trừ các phần định nghĩa và đối số mặc định của các hàm thành viên và mẫu chức năng thành viên. Tiêu chuẩn cũng định nghĩa khi các đối số mặc định của hàm được khởi tạo chính xác.

Vì vậy, đối số mẫu mặc định được khởi tạo ngay lập tức. Khả năng rằng đối số mặc định có thể được dự định bao gồm đối số mẫu mặc định tại thời điểm này rất nhỏ ở đây theo ý kiến ​​của tôi, vì không có mô tả khi nào một đối số đó sẽ được khởi tạo sau.

Điều này phù hợp với yêu cầu "Đối số mẫu mặc định sẽ không được chỉ định trong danh sách mẫu tham số định nghĩa của thành viên của mẫu lớp xuất hiện bên ngoài lớp của thành viên"., vì sẽ không có cách nào đối số mẫu như vậy được khởi tạo ngay lập tức khi khởi tạo mẫu lớp xung quanh.

+0

Nếu "đối số mẫu mặc định" được bao gồm trong "đối số mặc định", thì chúng cũng được đưa vào giải thích điểm giải thích, cho biết đó là điểm khởi tạo của mẫu chức năng. Tuy nhiên, tôi chủ yếu tự hỏi vì Clang chỉ chấp nhận tất cả các đoạn "như mong đợi". – Xeo

+0

@Xeo nhưng điều đó rất khó xảy ra, bởi vì nó chỉ nói về các cuộc gọi chức năng. Một đối số mẫu mặc định có thể được sử dụng không chỉ trong các cuộc gọi hàm, mà còn trong việc sử dụng các cá thể mẫu lớp của bất kỳ hương vị nào (trên thực tế, trường hợp duy nhất cho C++ 03) và chuyên môn hóa rõ ràng và diễn giải các mẫu hàm.Tất cả những gì không được đề cập ở bất kỳ đâu trong các quy tắc về sự khởi tạo ngầm cũng như các quy tắc về điểm khởi tạo. Tôi khuyên bạn nên mở một Clang PR. –

+0

@Xeo Ngoài ra, một đối số mẫu mặc định của hàm có thể được sử dụng mà không có sự khởi tạo hàm. Một cái gì đó như 'decltype (& X :: template foo <>)' có thể trả về nó nhưng hàm sẽ không được sử dụng ODR. Yêu cầu SFINAE trong bối cảnh đó sẽ ngụ ý quá tải độ phân giải mà nếu không sẽ không xảy ra. – Potatoswatter

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