2011-11-02 18 views
5

Tôi có một lớp mẫu cơ sở như thế này:Giới hạn chức năng được tạo khuôn mẫu cho các loại cơ sở và có nguồn gốc?

template<typename T, std::size_t Size> 
class VectorT 
{ 
public: 
    typedef T data_type; 
} 

và một vài các lớp thừa kế chuyên:

template<typename T> 
class Vector2d : public VectorT<T, 2U> 
{ // some specialised functions } 

template<typename T> 
class Vector3d : public VectorT<T, 3U> 
{ // some other specialised functions } 

và những công việc tốt. Howerver, tôi có một vài chức năng tự do cho các nhà khai thác. Ví dụ:

template<typename T, size_t Size> 
VectorT<T, Size> operator*(T lhs, const VectorT<T, Size>& rhs) 
{ 
    ... 
} 

Thật không may những không làm việc cho các lớp thừa kế của tôi, bởi vì họ trả về một VectorT<T, Size> thay vì một Vector2d<T>.

Vì vậy, tôi cố gắng với

template<V> 
V operator*(typename V::data_type lhs, const V& rhs) 
{ 
    ... 
} 

và điều này hoạt động tốt, tuy nhiên nó có thể dẫn đến sự mơ hồ bởi vì nó sucks trong bất cứ điều gì khác với một thành viên data_type.

Làm cách nào để khắc phục vấn đề này: làm cách nào để viết các chức năng an toàn loại chỉ hoạt động với cơ sở vectơ của tôi hoặc bất kỳ dẫn xuất nào?

Tôi đang cố gắng khám phá và xác định lại các toán tử một lần nữa cho các lớp con.

Trả lời

7

Bạn có thể thêm thêm một lớp cơ sở, một trong đó là không phụ thuộc vào các thông số mẫu, và sử dụng SFINAE để vô hiệu hóa các cuộc gọi với nhiều loại khác hơn là xuất phát từ cơ sở như:

struct VectorBase {}; 

template< typename T, std::size_t Size > 
class VectorT : public VectorBase { ... } 

template< typename V > 
typename boost::enable_if< boost::is_base_of< VectorBase, V >, V >::type 
operator*(V lhs, V const& rhs){ ... } 

Lưu ý rằng is_base_of< X, X > luôn là true, do đó chức năng này sẽ hoạt động đối với một loại khác so với yêu cầu, cụ thể là lớp cơ sở VectorBase.

Nếu bạn đang sử dụng trình biên dịch thực hiện TR1, bạn có thể thay thế boost:: cho std:: ở cả hai nơi được sử dụng.

+1

Cảm ơn bạn, đây là lần thứ hai tối nay bạn đã cho tôi câu trả lời liên quan đến SFINAE; Tôi nghĩ đây là nơi mà những khoảng trống trong kiến ​​thức của tôi nói dối! Tôi không chắc chắn chính xác cách enable_if hoạt động, nhưng điều này đã làm việc thực sự tốt. Cám ơn bạn một lần nữa. – DanDan

+0

@Kballo: liên quan đến việc thay thế 'boost ::' bằng 'std ::' -> lưu ý rằng 'std :: enable_if' tương đương với' boost :: enable_if_c', do đó bạn sẽ phải "unwrap" thành viên value' của 'is_base_of' khi chuyển sang' std :: '. –

1

Bạn đang ở trong một tình huống bất thường mà không có cách nào "đẹp". Bạn có thể:

  1. Kiểm tra các loại trong thời gian chạy (hoặc thời gian biên dịch, thúc đẩy có lẽ có thể làm điều đó)
  2. Hãy sử dụng và VectorT<>& rằng thay vì tạo ra một mới VectorT bên trong hàm và trả lại nó. Bằng cách này, bạn có thể lấy các lớp con của VectorT bằng cách tham chiếu. Điều đó sẽ làm cho bạn phải sử dụng một chức năng thay vì một nhà điều hành mặc dù.
  3. Thực hiện những gì K-ballo đã nói.
+1

Tôi thích tùy chọn 3 nhiều nhất: P –

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