2010-02-08 2 views
5

Trong khi làm việc trên một số mã đồ họa một thời gian trở lại, tôi đã viết các lớp Rect và Region bằng cách sử dụng ints như là người giữ tọa độ cơ sở, và nó hoạt động tốt. Vùng được triển khai như một phần mở rộng lớp đơn giản cho một danh sách STL và chỉ chứa một danh sách các Rects.Loại trình lặp nên có trong mẫu C++ này là gì?

Bây giờ tôi cũng cần các loại lớp tương tự bằng cách sử dụng đôi làm chủ tọa độ cơ bản, và quyết định thử tay của tôi tại templatizing nó. Vì vậy, tôi về cơ bản thay thế "int" với "typename T" một cách thông minh và cố định các vấn đề.

Nhưng có một vấn đề còn lại khiến tôi bối rối. Tôi muốn tính toán hộp giới hạn của Vùng bằng cách thực hiện một liên minh trên tất cả các Rects bao gồm nó. Điều đó hoạt động tốt khi không templatized, nhưng g ++ chokes trên danh sách iterator khi điều này được templatized.

Dưới đây là các mã có liên quan:

// Rect class that always remains normalized 
template <typename T> 
class KRect 
{ 
public: 

    // Ctors 
    KRect(void) 
     : _l(0), _t(0), _r(0), _b(0) 
    { 
    } 
    void unionRect(const KRect& r) 
    { 
     ... 
    } 

private: 
    T _l, _t, _r, _b; 
}; 

// Region class - this is very brain-dead 
template <typename T> 
class KRegion : public std::list< KRect<T> > 
{ 
public: 
    ... 

    // Accessors 
    KRect<T> boundingBox(void) 
    { 
     KRect<T> r; 
     iterator i; 
     for (i = this->begin(); i != this->end(); i++) 
     { 
      r.unionRect(*i); 
     } 
     return r; 
    } 
    ... 
}; 

Khi mã đó không phải là một phần của một mẫu, do đó T là nhất định (ví dụ một int), các "iterator i" dòng hoạt động tốt. Nhưng trong những gì bạn thấy ở trên, g ++ trên Ubuntu phát ra lỗi mà tôi không tìm thấy rất nhiều thông tin:

include/KGraphicsUtils.h: In member function ‘KRect<T> KRegion<T>::boundingBox()’: 
include/KGraphicsUtils.h:196: error: expected ‘;’ before ‘i’ 
include/KGraphicsUtils.h:197: error: ‘i’ was not declared in this scope 
include/KGraphicsUtils.h: In member function ‘KRect<T> KRegion<T>::boundingBox() [with T = int]’: 
--- redacted ---:111: instantiated from here 
include/KGraphicsUtils.h:196: error: dependent-name ‘std::foo::iterator’ is parsed as a non-type, but instantiation yields a type 
include/KGraphicsUtils.h:196: note: say ‘typename std::foo::iterator’ if a type is meant 

tôi đoán là đây là một bằng cấp vấn đề với một số loại mẫu-y quay Tôi không quen thuộc với. Tôi đã thử tất cả mọi thứ như:

std::list< KRect<T> >::iterator i; 
this->iterator i; 

nhưng không có gì có vẻ hiệu quả.

Mọi đề xuất?

+0

Bạn đang sử dụng trình biên dịch nào? Tôi có thể biên dịch nó trên VC++ 2010. – Jagannath

+0

Ông đã nói g ++ - VC++ theo truyền thống rất lỏng lẻo về các tên phụ thuộc không có 'typename' hoặc' template'. –

+0

Xin lỗi đã bỏ qua nó. – Jagannath

Trả lời

9

iterator là một loại phụ thuộc (nó phụ thuộc vào một mẫu đối số) và cần phải được bắt đầu bằng typename:

typename std::list< KRect<T> >::iterator i; 

phong cách tốt hơn sẽ được cung cấp một typedef tầm cỡ rộng:

template <typename T> 
class KRegion : public std::list< KRect<T> > 
{ 
    typedef std::list< KRect<T> > base; 
    typedef typename base::iterator iterator; 
    // ... 
}; 
+0

Điều đó đã sửa nó! gf, bạn là một quý ông và một học giả! –

3

Tôi nghĩ rằng gf has your answer, nhưng tôi muốn đề xuất rằng khu vực quản lý danh sách là thành viên thay vì một lớp cơ sở:

template <typename T> 
class KRegion 
{ 
protected: 
    typedef std::list< KRect<T> > ListType; 
    ListType list; 
public: 
    ... 
    // Accessors 
    void addRect(KRect<T> & rect) { list->push_back(rect); } 
    ... 
    KRect<T> boundingBox(void) 
    { 
     KRect<T> r; 
     ListType::iterator i; 
     for (i = list->begin(); i != list->end(); i++) 
     { 
      r.unionRect(*i); 
     } 
     return r; 
    } 
    ... 
}; 

Động lực của tôi cho đề xuất này là bạn có thể, một ngày nào đó, muốn sử dụng một vùng chứa khác để lưu trữ KRects của bạn và danh sách là thành viên nội bộ sẽ cho phép bạn làm như vậy mà không vi phạm tất cả mã khách hàng của bạn.

+0

e.James, bạn cũng là một quý ông và một học giả! Đó là một ý tưởng tuyệt vời; tuy nhiên, ngay bây giờ tôi muốn khách hàng có quyền truy cập trực tiếp vào danh sách thành viên vì tôi quá lười để viết tất cả những người truy cập. :-) –

+0

Đó là hoàn toàn công bằng ':)' Chúng tôi đã có tất cả ở đó. –

+0

Chỉ hy vọng không có khách hàng nào từng viết 'ListType * l = KRegion mới (); xóa l; '... –