2009-11-24 25 views
14

Có thể chuyển tiếp khai báo một lớp sử dụng đối số mặc định mà không chỉ định hoặc biết các đối số đó không?Các tham số mẫu mặc định với khai báo chuyển tiếp

Ví dụ: tôi muốn khai báo một lớp boost::ptr_list<TYPE> trong lớp Traits mà không cần kéo toàn bộ thư viện Boost vào mọi tệp bao gồm các đặc điểm. Tôi muốn tuyên bố namespace boost { template<class T> class ptr_list<T>; }, nhưng điều đó không làm việc bởi vì nó không chính xác phù hợp với khai báo lớp đúng:

template < class T, 
    class CloneAllocator = heap_clone_allocator, 
    class Allocator = std::allocator<void*> 
    > 
class ptr_list { ... }; 

đang lựa chọn của tôi chỉ để sống với nó hoặc để xác định boost::ptr_list< TYPE, boost::heap_clone_allocator, std::allocator<void*> trong lớp học đặc điểm của tôi không? (Nếu tôi sử dụng sau này, tôi cũng sẽ phải chuyển tiếp tuyên bố boost::heap_clone_allocator và bao gồm <memory>, tôi giả sử).

Tôi đã nhìn qua cuốn sách Stroustrup của, SO, và phần còn lại của mạng Internet và đã không tìm thấy một dung dịch. Thông thường mọi người lo ngại về việc không bao gồm STL và giải pháp là "chỉ bao gồm các tiêu đề STL". Tuy nhiên, Boost là một thư viện lớn hơn và biên dịch nhiều hơn, vì vậy tôi muốn bỏ nó ra, trừ khi tôi hoàn toàn phải làm vậy.

+1

Tăng là một tập hợp hầu hết các thư viện chỉ tiêu đề. Tại sao không chỉ sử dụng những thành phần bạn cần (và phụ thuộc của chúng)? Không phải để nói rằng không có một số công việc liên quan nhưng đó là những gì chúng ta thường làm. – dirkgently

+0

Tôi làm - ptr_list là tệp duy nhất tôi cần. Vấn đề duy nhất là một tiêu đề Boost đơn bao gồm một loạt các tiêu đề khác. Một ứng dụng đơn giản của makedepend cho thấy * chỉ * ptr_list bao gồm ít nhất 385 tệp: cấu hình của boost, chi tiết, trình lặp, mpl, tiền xử lý, phạm vi, smart_ptr, type_traits và tiện ích - để đặt tên cho các mô-đun chính. Bạn chắc chắn có thể hiểu làm thế nào tôi muốn tránh bao gồm cả những người khi tôi không phải. –

+0

Không có thắc mắc về thời gian biên dịch tăng vọt. Có, bao gồm nhiều tệp có thể gây phiền toái. Nhưng tôi nghĩ rằng các câu hỏi đúng là: có cách nào để tìm hiểu lý do tại sao các tệp này được đưa vào không? Các tệp được bao gồm có thể được chia để chỉ những thứ cần thiết được đưa vào hay không. Có vẻ như không phải là một cách dễ dàng. –

Trả lời

2

Bất kỳ đơn vị biên dịch nào sử dụng cơ sở của bạn mà công cụ tăng cường chuyển tiếp sẽ cần bao gồm tiêu đề tăng, ngoại trừ trường hợp bạn có một số chương trình không thực sự sử dụng phần tăng cường của cơ sở.

Đúng là bằng cách chuyển tiếp, bạn có thể tránh bao gồm tiêu đề tăng cho các chương trình như vậy. Nhưng bạn sẽ phải tự bao gồm các tiêu đề tăng (hoặc có một #ifdef) cho những chương trình thực sự sử dụng phần tăng cường.

Hãy nhớ rằng có thể thêm nhiều thông số mẫu mặc định hơn trong bản phát hành Tăng cường trong tương lai. Tôi khuyên bạn nên chống lại con đường này. Những gì tôi sẽ xem xét, nếu mục tiêu của bạn là để tăng tốc độ biên dịch, là sử dụng #define để cho biết liệu mã sử dụng thư viện tăng cường đó có bị vô hiệu hay không. Bằng cách này bạn tránh được rắc rối khai báo về phía trước.

+0

Vâng, có những phần thực sự trong mã của tôi không sử dụng thư viện Tăng nhưng lại bao gồm các tệp đặc điểm - đó là lý do tại sao câu hỏi này không hoàn toàn vô ích. Và có, tôi nhận thức được vấn đề tiềm ẩn với việc thay đổi các tham số mẫu. Đó là lý do tại sao tôi không thích một trong hai lựa chọn. –

+0

Ok. Vì vậy, bạn sử dụng khai báo chuyển tiếp, và sau đó các đơn vị biên dịch DO của bạn sử dụng thư viện boost chịu trách nhiệm tự bao gồm nó (thường thì tiêu đề của bạn sẽ bao gồm các tiêu đề tăng mà nó sử dụng). Dù bằng cách nào là gây phiền nhiễu, nhưng chấp nhận được. Rõ ràng là bạn có thể chia lớp đặc điểm thành hai phần khác nhau có tiêu đề khác nhau (thậm chí có phần nâng cao được thừa kế từ phần không tăng) nhưng điều đó có vẻ thô và sẽ làm cho việc này trở nên khó chịu hơn. –

7

Tôi không nghĩ bạn có thể chuyển tiếp tuyên bố mẫu với đối số mặc định trừ khi thư viện được đề cập cung cấp tiêu đề khai báo chuyển tiếp của riêng nó. Điều này là do bạn không thể respecify các đối số mặc định (ngay cả khi họ phù hợp ... gcc sẽ vẫn báo cáo "lỗi: redefinition của đối số mặc định").

Vì vậy, để sự hiểu biết của tôi, giải pháp là cho thư viện để cung cấp một về phía trước tiêu đề khai Foo_fwd.h:

#ifndef INCLUDED_Foo_fwd_h_ 
#define INCLUDED_Foo_fwd_h_ 
template<class T, class U=char> class Foo; // default U=char up here 
#endif 

và sau đó thực hiện đầy đủ trong foo.h sẽ là:

#ifndef INCLUDED_Foo_h_ 
#define INCLUDED_Foo_h_ 
#include "Foo_fwd.h" 
template<class T, class U> class Foo { /*...*/ }; // note no U=char here 
#endif 

Vì vậy, bây giờ mã của bạn cũng có thể sử dụng Foo_fwd.h ... nhưng không may, vì phương pháp này yêu cầu sửa đổi Foo.h gốc để xóa các đối số mặc định không quy mô cho thư viện của bên thứ ba. Có lẽ chúng ta nên vận động cho phi hành đoàn C++ 0x để cho phép tương đương tương ứng với các đối số mẫu mặc định, à la typedefs ...?

0

Vấn đề tương tự ở đây. Nhưng với STL.

Nếu một trong các tiêu đề của tôi sử dụng ví dụ: std :: vector sau đó tôi phải bao gồm toàn bộ tiêu đề. Từ thời điểm này mỗi lần tôi đưa tiêu đề của mình ngay cả khi mã nguồn của tôi không tham chiếu đến std :: vector ở tất cả các tiêu đề được đưa vào cùng với tiêu đề của tôi. Nếu bạn bao gồm tiêu đề này ở rất nhiều nơi sẽ có nghĩa là rất nhiều overparsing.

Vì vậy, tôi chuyển tiếp tuyên bố std :: vector và được sử dụng std :: vector * nhưng mã của tôi không muốn biên dịch do các đối số mặc định. Nếu tôi đặt các đối số mặc định trong tiêu đề của tôi thì trình biên dịch từ chối biên dịch tiêu đề stl do sự tuân thủ đối số mặc định.

Điều tôi đang cố gắng làm trong trường hợp này là tạo lớp Vector của riêng mình điều chỉnh std :: vector và chuyển tiếp mọi lời gọi phương thức tới nó. Có lẽ điều này có thể giải quyết vấn đề.

+0

Trong trường hợp bạn mô tả, tất cả những điều không chắc chắn đó không phải là nỗ lực. Hình phạt duy nhất trong trường hợp của bạn là (biên dịch gcc rất nhỏ thời gian có và không có '#include ') hình phạt thời gian biên dịch tải một vài tệp. Sử dụng một con trỏ tới một vectơ, hoặc thêm một lớp bao bọc, sẽ làm phức tạp cuộc sống của bạn, thêm các hình phạt thời gian chạy có thể, và thậm chí sẽ không giải quyết được vấn đề vì cách thức các khuôn mẫu làm việc. –

+0

Tôi chưa viết bất kỳ mã nào về điều đó và có vẻ như tôi không nên ... Có vẻ như tôi cần phải bao gồm tiêu đề vào tiêu đề của tôi. Tôi đọc trong một chủ đề khác mà các dự án C++ thực sự lớn đang biên dịch trung bình 30-60 phút sau mỗi tối ưu hóa biên dịch do tiền xử lý và điều mẫu. Đó là một thất bại của C + + phải không? – Calmarius

11

Có. Các đối số mẫu mặc định có thể được chỉ định bất kỳ lúc nào, ở bất kỳ đâu, miễn là các khai báo không xung đột với nhau. Chúng cuối cùng được hợp nhất với nhau từ các tờ khai khác nhau.

Ngay cả điều này là hợp pháp:

template< class A, class B, class C = long > 
class X; 

template< class A, class B = int, class C > 
class X; 

template< class A = short, class B, class C > 
class X { }; 

Một ví dụ tương tự được đưa ra trong §14.1/10. Theo đoạn đó, các đối số mặc định của hàm hoạt động tương tự.

Chúc bạn may mắn khi nhận được tờ khai chuyển tiếp để hành xử và không bị chặn trên mọi thứ!

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