2017-10-23 39 views
11
#include <utility> 

template<class T1, class T2> 
struct mypair : std::pair<T1, T2> 
{ using std::pair<T1, T2>::pair; }; 

int main() 
{ 
    (void)std::pair(2, 3); // It works 
    (void)mypair(2, 3); // It doesn't work 
} 

Hình thức trên cũng được hình thành?Khoản khấu trừ đối số mẫu lớp không thành công với lớp dẫn xuất

Có thể suy ra các đối số mẫu lớp trong trường hợp thứ hai nếu các hàm tạo đang được kế thừa không? Các nhà thầu của std::pair có tham gia tạo các hướng dẫn khấu trừ ngầm cho mypair không?

Trình biên dịch của tôi là g ++ 7.2.0.

+0

Khi ADL được thực hiện bằng cách sử dụng std :: pair :: pair; bị bỏ qua –

+0

@HariomSingh - Bạn có thể sao lưu nó không? Tôi cũng nghĩ thế. Nhưng sau đó [namespace.udecl]/16. – StoryTeller

+0

@StoryTeller vâng tôi đang làm việc trên ví dụ. Xem xét các quy tắc của ADL –

Trả lời

4

Tôi nghĩ rằng đây là lỗi gcc (hoặc ít nhất là lỗi ngôn ngữ lõi nhỏ).

nhà xây dựng Kế thừa làm tính là nhà thầu, theo [namespace.udecl]/16:

Likewise, constructors that are introduced by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class ([class.qual]) or forming a set of overload candidates ([over.match.ctor], [over.match.copy], [over.match.list])

Danh sách đó điều kiện về mặt kỹ thuật không bao gồm [over.match.class.deduct], nhưng ngụ ý là cơ sở các nhà xây dựng lớp học các nhà xây dựng của lớp dẫn xuất. Và quy tắc trong [over.match.class.deduct] là để xem xét:

If C is defined, for each constructor of C , a function template with the following properties [...]

Chúng tôi nhìn lên constructor của lớp được thừa kế, chỉ cần không phải trong các trường hợp được liệt kê. Nhưng ví dụ này nên làm việc khái niệm:

template <class T> struct base { base(T) { } }; 
template <class T> struct derived : base<T> { using base<T>::base; }; 

base b = 4; // ok 
derived d = 4; // error 
+0

clang có lỗi cho cả main.cpp: 10: 16: lỗi: không thể tham chiếu đến lớp mẫu 'cặp' mà không có danh sách đối số mẫu (void) std :: pair (2, 3) ; // Nó hoạt động ~~~~~^ /usr/include/C++/v1/tiện ích: 248: 30: lưu ý: mẫu được khai báo ở đây struct _LIBCPP_TYPE_VIS_ONLY pair ^ main.cpp: 11: 11: error: không thể tham khảo mẫu lớp 'mypair' mà không có danh sách đối số mẫu (void) mypair (2, 3); // Nó không hoạt động ^ main.cpp: 5: 8: lưu ý: mẫu được khai báo ở đây struct mypair: std :: pair ^ 2 lỗi được tạo. –

+0

http://coliru.stacked-crooked.com/view?id=4d48dfb916abc109 –

+0

@HariomSingh chỉ clang 5 có hỗ trợ cho việc khấu trừ các tham số mẫu lớp, chưa có trong coliru. –

2

Câu chuyện ngắn: không có quy tắc trong tiêu chuẩn mà nói thế nào điều này sẽ làm việc, cũng không phải bất kỳ quy tắc mà nói rằng nó không hoạt động. Vì vậy, GCC và Clang thận trọng từ chối hơn là phát minh ra một quy tắc (phi tiêu chuẩn).

Câu chuyện dài: Lớp cơ sở là loại phụ thuộc, do đó, tra cứu các nhà xây dựng của nó không thể thành công. Đối với mỗi chuyên môn của mytype<T1, T2>, các nhà thầu tương ứng của pair<T1, T2> là các nhà thầu của mytype, nhưng đây không phải là quy tắc có thể được áp dụng có ý nghĩa cho mẫu trước khi diễn giải nói chung.

Về nguyên tắc, có thể có quy tắc nói rằng bạn xem xét các nhà xây dựng của mẫu chính pair trong tình huống này (giống như khi chúng ta tự tìm kiếm các nhà xây dựng của mypair để khấu trừ đối số mẫu lớp), nhưng không có quy tắc thực sự tồn tại trong tiêu chuẩn hiện tại. Tuy nhiên, quy tắc như vậy nhanh chóng rơi xuống khi lớp cơ sở trở nên phức tạp hơn:

template<typename T> struct my_pair2 : std::pair<T, T> { 
    using pair::pair; 
}; 

Những người xây dựng nào cần được đưa vào đây? Và trong những trường hợp như thế này, tôi nghĩ rằng đó là một cách hợp lý rõ ràng rằng tra cứu này không thể nào làm việc:

template<typename T> struct my_pair3 : arbitrary_metafunction<T>::type { 
    using arbitrary_metafunction<T>::type::type; 
}; 

Có thể chúng tôi sẽ có được một sự thay đổi quy tắc cho phép khấu trừ qua my_pair của bạn và my_pair2 trên nếu/khi chúng tôi nhận lớp các quy tắc khấu trừ đối số mẫu cho các mẫu bí danh:

template<typename T> using my_pair3 = std::pair<T, T>; 
my_pair3 mp3 = {1, 2}; 

Sự phức tạp liên quan ở đây phần lớn giống như trường hợp xây dựng kế thừa.Faisal Vali (một trong những nhà thiết kế khác về khấu trừ đối số mẫu lớp) có một kế hoạch cụ thể về cách làm cho các trường hợp như vậy hoạt động, nhưng ủy ban C++ chưa thảo luận về phần mở rộng này.

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