2011-10-12 37 views
5

tôi có một tập hợp của các loại liên quan đến một mối quan hệ one-to-one, ví dụ:Bản đồ hai loại tại thời gian biên dịch

TypeA ---> Type1 
TypeB ---> Type2 
TypeC ---> Type3 

Tôi biết những mối quan hệ tại thời gian biên dịch.

Sau đó, tôi có một lớp mẫu mà phụ thuộc vào này hai loại:

template<class T1,class T2> 
class MyClass 
{ 
    T1 foo; 
    T2 bar; 
}; 

Bây giờ, người sử dụng thư viện của tôi sẽ gõ cái gì đó như:

MyClass<TypeA,Type1> x; 

Đây là bất tiện vì không một sự phụ thuộc giữa hai loại và nó sẽ là đủ cho người dùng chỉ định kiểu đầu tiên.

Ngoài ra, trộn hai loại không nên có thể:

MyClass<TypeA,Type2> y; //it should not compile 

Tôi không phải là rất quen thuộc với lập trình meta mẫu, tôi có cảm giác rằng đây là nhiệm vụ khả thi, nhưng tôi có thể sai.

Số lượng loại có liên quan là lớn, tuy nhiên tôi rất vui khi chạy tập lệnh để tạo mã nếu cần.

Bạn có biết nếu có thể hoặc tôi đang lãng phí thời gian của mình? Bạn có ý tưởng nào để chỉ cho tôi đúng hướng không?

Trả lời

6
template<class T> 
struct get_mapped; 

template<> 
struct get_mapped<TypeA>{ 
    typedef Type1 type; 
}; 

// and so on.... 


template<class T> 
class MyClass{ 
    typedef typename get_mapped<T>::type T2; 

    T foo; 
    T2 bar; 
}; 
3

Tại sao không chỉ tạo ra một loại wrapper:

template <typename T1, typename T2> 
struct wrapper 
{ 
    typedef T1 type1; 
    typedef T2 type2; 
}; 

typedef wrapper<TypeA, Type1> TypeX; 
typedef wrapper<TypeB, Type2> TypeY; 
typedef wrapper<TypeC, Type3> TypeZ; 

Sau đó, người sử dụng cho biết, MyClass<TypeX>;, và bạn xác định:

template <typename T> 
class MyClass 
{ 
    typename T::type1 foo; 
    typename T::type2 bar; 
}; 

Nếu bạn muốn bảo vệ chống lại sự lạm dụng của mẫu, sử dụng một chuyên môn từng phần:

template <typename> class MyClass; // undefined 

template <typename S, typename T> 
class MyClass<wrapper<S,T>> 
{ 
    S foo; 
    T bar; 
}; 

Cách tiếp cận này có thể dễ dàng được mở rộng để bao gồm thêm biên dịch dữ liệu thời gian vào lớp trình bao bọc. Ngoài ra, bạn có thể sử dụng std::pair với các loại thành viên first_typesecond_type để thay thế.

5
template<class T> struct TypeLetter2TypeDigit; 

template<> struct TypeLetter2TypeDigit<TypeA> { typedef Type1 type; }; 
template<> struct TypeLetter2TypeDigit<TypeB> { typedef Type2 type; }; 
template<> struct TypeLetter2TypeDigit<TypeC> { typedef Type3 type; }; 


template<class T1> // Type2 is not needed 
class MyClass 
{ 
    // Type2 is deduced. 
    typedef typename TypeLetter2TypeDigit<T1>::type T2; 
    T1 foo; 
    T2 bar; 
}; 
+0

Thực hiện một số chỉnh sửa. Xem nếu nó là thích hợp. (Ngoài ra, bạn có thực sự cần một tên dài 'TypeLetter2TypeDigit'? IMHO một cái gì đó như' TypeMap' là đủ.) – iammilind

+0

@iammilind. Cảm ơn bạn. Tên dài là cần thiết để hiển thị những gì tôi muốn. Bạn hoặc OP có thể sử dụng bất kỳ tên nào. –

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