2009-09-30 35 views
5

Tôi đang cố gắng đúc từ một generic khác, nói:C++ Templates loại đúc với derivates

myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject; 

Hoặc làm một cái gì đó giống như

aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject 

nơi aFunction chữ ký là

aFunction(myClass<MoreAbstract> item); 

Trên thực tế, myClass thực sự là một cài đặt đơn giản của shared_ptr mà tôi tìm thấy trực tuyến. Tôi tự hỏi nếu có bất kỳ cách nào tôi thực sự có thể chuyển đổi từ một loại con trỏ khác đang được đóng gói.

Có cách nào để thực hiện việc truyền như vậy không? Nếu có, thì cách nào để làm đúng?

Nếu nó giúp bất cứ ai, VC++ mang lại cho tôi lỗi này:

Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>' 
+1

Đây có phải là một C++ ròng. generics hoặc một câu hỏi mẫu C++? –

+0

@Yannick: mẫu C++. – tomzx

Trả lời

10

Bạn không thể truyền tĩnh vì chúng là các loại không tương thích. Đôi khi bạn có thể tạo một nhà điều hành để ép buộc các loại thay vì

#include <iostream> 

class A { }; 

class B : public A { }; 


template<typename T> 
struct holder { 
    T* value; 

    holder (T*value) : value (value) { } 

    template < typename U > // class T : public U 
    operator holder<U>() const 
    { 
     return holder<U>(value); 
    } 
}; 


int main() 
{ 
    using namespace std; 

    B b; 

    holder<B> hb (&b); 
    holder<A> ha = hb; 

    cout << boolalpha; 

    cout << (hb.value == ha.value) << endl; 

    return 0; 
} 

Cho dù đây là một hoạt động có ý nghĩa chứ không phải phụ thuộc vào ngữ nghĩa của lớp mẫu - nếu aFunction có thể đặt bất cứ điều gì vào xử lý, bạn không muốn đối tượng cụ thể hơn bị đột biến. Do đó bạn sao chép bằng cách nào đó, hoặc với một nhà điều hành cưỡng chế hoặc với một nhà xây dựng bản sao mẫu và nhiệm vụ. (cưỡng chế là ít mã hơn nhưng có thể dẫn đến nhiều đối tượng được tạo nếu bạn không sử dụng tham số)

+2

Tôi muốn một nhà xây dựng chuyển đổi cho một nhà điều hành chuyển đổi vì sau này không thể được kích hoạt hoặc vô hiệu hóa –

+0

@Pete Kirkham: Tôi cần sự giúp đỡ của bạn. Tại sao bạn sử dụng mẫu bên trong cấu trúc chủ? Mục đích của nó là gì? Trong bình luận bạn đã viết // class T: public U. Nó có nghĩa là gì? – Destructor

3

Xin lỗi, có nghĩa là không thể. (Vâng, trừ khi bạn làm khó chịu reinterpret_cast hack, nhưng bạn không muốn làm điều đó - kết quả cuối cùng sẽ không được đẹp).

T<Base>T<Derived> không liên quan. Trình biên dịch không thể giả định rằng - hãy nhớ rằng hoàn toàn có thể là T đã được chuyên biệt hóa để có được một cái gì đó hoàn toàn khác nhau.

1

Mẫu trong C++ cũng như generics trong C++. Net không phải là biến thể.

Kiểm tra câu hỏi this, có thể cung cấp cho bạn ý tưởng giải pháp.

6

Các loại không thể chuyển đổi mặc định theo cách này (vì bạn có thể không muốn đối tượng làm điều đó). Nói chung, bạn có thể thực hiện hai cách tiếp cận:

Thực hiện chức năng truyền rõ ràng, có thể hữu ích cho phôi thời gian, như boost's shared_ptr dynamic_pointer_cast. Bạn sẽ kết thúc với một cái gì đó như:

template <typename To, typename From> 
myclass<To> myclass_cast(const myclass<From>&) 
{ /* do a runtime cast, possibly with exceptions */ } 

Phương pháp thứ hai là một hàm tạo chuyển đổi, tốt nếu nó có thể được giải mã tại thời điểm biên dịch nếu chúng có thể chuyển đổi. Ví dụ, nếu tất cả các lớp học là convertable từ templated trên nguồn gốc để templated trên cơ sở, đây là một nhà xây dựng mà sẽ chỉ làm việc khi đó là sự thật (sử dụng enable_if và đẩy mạnh :: type_traits):

template <typename To> 
class myclass { 
    //converting constructor 
    template <typename From> 
    myclass(const myclass<From>&, 
      typename enable_if<boost::type_traits::is_base_of<To, From> >::type* dummy = 0) 
    { } 
};