2009-07-15 26 views
8

Tôi có một lớp container, chúng tôi sẽ gọi nó làcon trỏ làm thông số mẫu?

template <class T> CVector { ... } 

tôi muốn làm một cái gì đó khác nhau với lớp này khi T là một kiểu con trỏ, ví dụ một cái gì đó dọc theo các dòng:

template <class T*> CVector< SomeWrapperClass<T> >; 

trong đó SomeWrapperClass đang chờ loại thông tin được trỏ đến làm thông số của nó. Thật không may, cú pháp này không hoàn toàn làm việc và với một số đào, tôi đã không tìm thấy một cách tốt để có được một cái gì đó như thế này làm việc.

Tại sao thực hiện theo cách này? Tôi muốn thay đổi, trong một ứng dụng rất lớn, cách một số thùng chứa của chúng tôi hoạt động khi loại chúng chuyên biệt là con trỏ chứ không phải con trỏ - và lý tưởng, tôi muốn làm điều đó mà không thay đổi ~ 1.000 địa điểm trong mã có những thứ như CVector<Object*> vs CVector<int> hoặc một số trò chơi như vậy và chơi với các chuyên môn từng phần dường như là cách để đi.

Tôi có bị nứt ở đây không?

+0

Tôi nghĩ cần có nhiều ngữ cảnh hơn cho những gì bạn đang làm. Vậy, cái này là gì? Lớp bao bọc "Một số" là gì? Và 'CVector' là gì? Không phải là một 'std :: vector' được sáng tạo lại, tôi hy vọng. – GManNickG

+0

Không, không phải - tôi đang sử dụng các tên trừu tượng cho các lớp cố ý - nhưng về cơ bản lớp bao bọc lấy một kiểu không phải con trỏ làm tham số của nó. CVector có thể lấy bất kỳ kiểu kiểu nào - tôi chỉ muốn sử dụng lớp wrapper khi vector được đưa ra một kiểu con trỏ. –

+0

@D Garcia: Tôi không hiểu những gì bạn muốn, chính xác. Nếu T là một con trỏ, CVector nên làm gì? – rlbond

Trả lời

4

Tôi không nghĩ rằng bạn có thể chuyên môn một lớp bằng cách sử dụng cú pháp bạn mô tả ... Tôi không biết làm thế nào mà có thể có thể làm việc. Những gì bạn có thể làm là chuyên lớp cho con trỏ và thực hiện lại các đường ruột của nó bằng cách sử dụng lớp wrapper quanh các con trỏ thô. Tôi không chắc chắn nếu nó sẽ giúp đỡ, nhưng this article mô tả các mẫu chuyên cho con trỏ.

+0

Cảm ơn bạn - bài viết bạn đã liên kết đã cho tôi một cách để làm những gì tôi cần. –

+0

Vui vì tôi có thể giúp đỡ. Tôi không cho rằng bạn muốn chấp nhận câu trả lời của tôi, hoặc ít nhất là đưa ra một upvote, để thể hiện sự đánh giá cao? :) – rmeador

+0

Liên kết tốt, có một upvote uphote XP – jaypb

0

Tôi không nghĩ rằng các mẫu khá linh hoạt.

Một phương pháp tiếp cận rất mạnh sẽ là chuyên cho tất cả các loại con trỏ của bạn ... đánh bại vấn đề sử dụng mẫu.

Bạn có thể có lớp CVector khác chỉ được sử dụng cho vectơ của con trỏ không?

+0

Nếu tôi đã thực hiện một loại khác nhau, tôi sẽ phải đi qua tất cả các nơi trong mã mà loại cũ đã được sử dụng để lật nó sang loại mới - ít hơn lý tưởng , tôi đang tìm kiếm một sự thay thế. –

7

Nếu tôi hiểu bạn một cách chính xác, điều này có thể làm những gì bạn muốn:

template<typename T> 
class CVector { ... }; 

template<typename T> 
class CVector<T*> : public CVector< SomeWrapperClass<T> > { 
public: 
    // for all constructors: 
    CVector(...) : CVector< SomeWrapperClass<T> >(...) { 
    } 
}; 

Nó cho biết thêm thêm một lớp thừa kế để lừa CVector<T*> ra đời một CVector< SomeWrapperClass<T> >. Điều này cũng có thể hữu ích trong trường hợp bạn cần thêm các phương thức bổ sung để đảm bảo khả năng tương thích đầy đủ giữa giao diện được mong đợi cho T* và giao diện được cung cấp cho SomeWrapperClass<T>.

+0

Hmm - nếu tôi có thể có lớp mới được đặt tên giống như cũ - điều này có thể hoạt động. Nếu tôi phải đổi tên lớp, tôi quay lại việc phải thay đổi tất cả các instantiations thành một lớp mới, đó là công việc tôi đang cố gắng tránh phải làm. –

+0

Nó vẫn chỉ là một 'CVector <...>', chỉ là nó có thể kế thừa từ một 'CVector <...>' nội bộ khác nhau. Nhưng người dùng của lớp không nên quan tâm đến các chi tiết bên trong này, miễn là giao diện vẫn tương thích. – sth

+0

+1 @Garcia: Giải pháp trên nên hoạt động - bạn có thể tham khảo việc sử dụng mẫu CVector như CVector vs CVector - và mẫu thích hợp sẽ được sử dụng (được thực hiện dưới dạng SomeWrapper và không) –

4

này chỉ hoạt động tốt trong C++ ...

#include <iostream> 

template <class T> 
class CVector 
{ 
public: 
    void test() { std::cout << "Not wrapped!\n"; } 
}; 

template <class T> 
class CVector<T*> 
{ 
public: 
    void test() { std::cout << "Wrapped!\n"; } 
}; 

int main() 
{ 
    CVector<int> i; 
    CVector<double> d; 
    CVector<int*> pi; 
    CVector<double*> pd; 
    i.test(); 
    d.test(); 
    pi.test(); 
    pd.test(); 
} 
+0

Điều đó sẽ không hãy để tôi thay đổi một tham số mẫu có điều kiện về việc nó có phải là một con trỏ hay không - đã xem xét những gì tăng có. Đây không phải là trường hợp mã có điều kiện - đó là trường hợp gõ có điều kiện - các loại thứ bên trong lớp cần phải khác nhau dựa vào việc tham số mẫu có phải là một con trỏ hay không. –

1

Các Boost type traits library có thể giúp bạn đạt được điều này. Hãy xem đặc điểm loại is_pointer.

#include <boost/type_traits.hpp> 
#include <iostream> 
#include <vector> 

using namespace std; 

template <class T> 
class CVector { 
    public: 
    void addValue(const T& t) { 
     values_.push_back(t); 
    } 

    void print() { 
     typedef boost::integral_constant<bool, 
     ::boost::is_pointer<T>::value> truth_type; 

     for (unsigned int i = 0; i < values_.size(); i++) 
     doPrint(values_[i], truth_type()); 
    } 


    private: 
    void doPrint(const T& t, const boost::false_type&) { 
     cout << "Not pointer. Value:" << t << endl; 
    } 

    void doPrint(const T& t, const boost::true_type&) { 
     cout << "Pointer. Value: " << *t << endl; 
    } 

    std::vector<T> values_; 
}; 


int main() { 
    CVector<int> integers; 
    integers.addValue(3); 
    integers.addValue(5); 
    integers.print(); 

    CVector<int*> pointers; 
    int three = 3; 
    int five = 5; 
    pointers.addValue(&three); 
    pointers.addValue(&five); 
    pointers.print(); 
} 
0

Tôi đồng ý với câu trả lời của rlbond. Tôi đã sửa đổi nó một chút cho phù hợp với nhu cầu của bạn. CVector có thể là một lớp dẫn xuất của chính CVector. Sau đó, bạn có thể sử dụng các thành viên và chức năng khác nhau cho nó.

#include <iostream> 
#include <string> 
template <class T> 
class CVector 
{ 
public: 
    void test() { std::cout << "Not wrapped!\n"; } 
    void testParent() { std::cout << "Parent Called\n";} 
}; 

template <class T> 
class CVector<T*>: 
    public CVector<T> 
{ 
public: 
    void test(std::string msg) { std::cout << msg; testParent(); } 
}; 

int main() 
{ 
    CVector<int> i; 
    CVector<double> d; 
    CVector<int*> pi; 
    CVector<double*> pd; 
    i.test(); 
    d.test(); 
    pi.test("Hello\n"); 
    pd.test("World\n"); 
    system("pause"); 
} 
Các vấn đề liên quan