2016-10-02 19 views
10

Hãy xem xét ví dụ này (also available on wandbox):Liệu C++ 17 có thể suy ra các mẫu tham số mẫu `match` không kiểu` mẫu` với các tham số không kiểu rõ ràng không?

template <template <auto> class> 
void test() { } 

template <int> 
struct X { }; 

Đang cố gắng để nhanh chóng test<X>() trên clang++ 4,0 (thân cây) kết quả trong một lỗi biên dịch:

error: no matching function for call to 'test' 
    test<X>(); 
    ^~~~~~~ 

note: candidate template ignored: 
     invalid explicitly-specified argument for 1st template parameter 
void test() { } 

My ban đầu giả định/trực giác là test có thể được sử dụng để khớp với bất kỳ số template nào có thông số không phải loại.


Tuy nhiên, đoạn mã sau biên dịch thành công:

template <template <auto> class> 
void test() { } 

//  vvvv 
template <auto> 
struct X { }; 

Đây có phải là mục đích? Không thể tìm thấy bất kỳ điều gì kết thúc trong số P0127R2.

+0

Trong tiêu đề, ý của bạn có phải là "được suy luận" không? –

Trả lời

9

Đó chắc chắn là dự định. Các tham số mẫu-mẫu chỉ có thể khớp với các mẫu có cùng các loại đối số. Đây:

template <template <auto> class> 
void test() { } 

chỉ có thể được khởi tạo với một lớp mẫu có thể mất bất cứ loại tham số không kiểu. Nhưng điều này:

template <int> 
struct X { }; 

không phải là mẫu lớp như vậy. X chỉ có thể được khởi tạo với int. Nó chỉ đơn giản là không phù hợp với đặc điểm kỹ thuật cho tham số mẫu template, do đó lỗi. Điều gì sẽ xảy ra nếu test muốn khởi tạo mẫu lớp của nó bằng một kiểu con trỏ? Hoặc con trỏ đến hàm hoặc con trỏ tới thành viên? Điều đó là không thể.

Lần thử thứ hai của bạn, với template <auto> struct X { };không khớp với thông số mẫu-mẫu, do đó được tạo đúng. Cũng lưu ý rằng ngược lại, có test lấy tham số template <int> class và đi qua trong template <auto> struct X { }; cũng được định dạng tốt vì đối số tổng quát hơn tham số.


Các từ ngữ có liên quan là trong [temp.arg.template]:

A template-argument matches a template template-parameterP when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template A matches the corresponding template parameter in the template-parameter-list of P . Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent (14.5.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively.


Lưu ý: cách diễn đạt tương đương chấp nhận auto - trường hợp auto và từ chối auto - trường hợp int, nhưng cũng dường như từ chối trường hợp int - auto (dựa trên việc đọc của tôi). Tôi sẽ cố gắng giải thích nó.

+0

Bất kỳ kết quả nào cho yêu cầu làm rõ của bạn? –

+0

@ JohannesSchaub-litb [nope] (https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/xVUfSpP0_48) – Barry

2

Ngoài câu trả lời của Barry, khiến tôi tò mò, đây là bốn tổ hợp có thể và kết quả sử dụng Clang 4,0 (SVN), see also on wandbox:

template <bool> struct obj_bool { }; // object taking a value of boolean type 
template <auto> struct obj_auto { }; // object taking a value of deduced type 
//  ^^^^^^ Note: this is a template value argument (non-type template argument) 

template <template <auto> typename> void fn_auto() { } 
template <template <bool> typename> void fn_bool() { } 
//  ^^^^^^^^^^^^^^^^^^^^^^^^ Note: this is a template type argument 
//     ^^^^^^    taking a template value argument 

int main() {  
    fn_bool<obj_bool>(); // #1 bool->bool OK (exact match) 
    fn_auto<obj_auto>(); // #2 auto->auto OK (exact match) 
    fn_bool<obj_auto>(); // #3 bool->auto OK (sub-set) 
    //fn_auto<obj_bool>(); // #4 auto->bool Error: no matching function. 
} 

Từ đó, # 1 và # 2 là rõ ràng chính xác phù hợp và đang hoạt động như mong đợi.# 3 sẽ gọi thực thi bool trên một khuôn mẫu có thể xử lý không chỉ bool nhưng tất cả các loại, trong khi # 4 sẽ cố gắng gọi một định nghĩa mong đợi một đối tượng tổng quát (tự động) với một đối tượng chỉ cung cấp một tập con (bool) các khả năng .

Chức năng templated fn_auto hứa hẹn các cảnh báo có thể có cho các mẫu sử dụng bất kỳ loại giá trị nào (tự động). Vì vậy, chỉ cho nó một tập hợp các khả năng (bool) vi phạm lời hứa này.

Mặc dù không rõ ràng ngay lập tức, hạn chế này có ý nghĩa. Và xin lỗi vì từ ngữ của tôi không tuân thủ chuẩn C++.

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