2011-11-03 16 views
9

Tôi có một vấn đề mà tôi cần phải khám phá tổ tiên chung của hai loại (với một hoặc không có lớp cơ sở) nếu nó tồn tại. Có thể xây dựng đặc điểm kiểu để giải quyết vấn đề này không? Trong mã:Làm thế nào để suy ra, tại thời gian biên dịch, gốc của một cây thừa kế chung với hai loại nếu một tồn tại?

template<typename T1, typename T2> 
    struct closest_common_ancestor 
{ 
    typedef XXX type; // what goes here? 
}; 

Với các loại sau đây:

struct root {}; 
struct child1 : root {}; 
struct child2 : root {}; 
struct child3 : child2 {}; 
struct unrelated {}; 

closest_common_ancestor sẽ cho kết quả trong các loại sau đây:

closest_common_ancestor<root, child1>::type == root 
closest_common_ancestor<child1, child2>::type == root 
closest_common_ancestor<child3, child1>::type == root 
closest_common_ancestor<child3, child2>::type == child2 
closest_common_ancestor<unrelated, child1>::type == error 

Tôi tin rằng tôi có thể giải quyết vấn đề này nếu tôi có thể kiểm tra liệu một loại có 0 hoặc một lớp cơ sở, và nếu như vậy, tên của loại đó. Điều này có thể không?

+2

Bạn không thể kiểm tra các lớp cơ sở. Không, trừ khi bạn thêm thông tin meta vào từng lớp của bạn theo cách thủ công. –

+0

Lưu ý rằng đối với một mối quan hệ trực tiếp nó đã có thể ('is_base_of' có thể được thực hiện theo khối C++ 03 cơ bản) –

+0

Nếu có 2 gốc' root1' và 'root2', và' child1', 'child2' kế thừa cả hai ('struct child1: root1, root2 {};'), nó sẽ không rõ ràng cho 'closest_common_ancestor' những gì cần trả về. – kennytm

Trả lời

7

Như K-ballo đã đề cập, thật không may là không thể có được danh sách các căn cứ mà một lớp có (quá tệ ...).

Nếu bạn chú thích theo cách thủ công các lớp của bạn (ví dụ: xác định đơn giản std::tuple<> liệt kê các căn cứ), thì bạn có thể sử dụng thông tin này. Các đơn giản hơn, tất nhiên, sẽ được sử dụng một đặc điểm:

template <typename> struct list_bases { typedef std::tuple<> type; }; 

Sau đó, bạn có thể chuyên đặc điểm này với nhiều loại bạn:

template <> struct list_bases<child1> { typedef std::tuple<root> type; }; 

Và bắt đầu từ đó, bạn có thể bắt đầu thử nghiệm với việc tìm kiếm tổ tiên ... tuy nhiên nó có thể không ngay lập tức. Ngoài các chi tiết thực hiện (nhận được các căn cứ đệ quy, thực hiện lựa chọn "khoảng cách"), tôi mong đợi một vấn đề với các trường hợp "lạ".

Việc lựa chọn khoảng cách có thể, trong thông thường (tuyến tính) hệ thống phân cấp thừa kế được giải quyết bằng cách sử dụng một sự kết hợp của is_base_ofis_same, tuy nhiên xem xét các hệ thống phân cấp như sau:

struct root1 {}; struct root2 {}; 

struct child1: root1 {}; struct child2: root2 {}; 

struct child12: root1, child2 {}; struct child21: root2, child1 {}; 

Bây giờ, child12child21 có hai tổ tiên chung: root1root2 ... gần nhất?

Chúng tương đương nhau. Hãy xem xét rằng tôi thêm:

struct root3 {}; struct child31: root3, child1 {}; 

Sau đó root1 là một tổ tiên chung để child12, child21child31.

Tuy nhiên nếu tôi đi theo định nghĩa closest_common_ancestor và tự ý xác định rằng closest_common_ancesotr<child12, child21>root2, thì tôi không thể tìm thấy bất kỳ tổ tiên chung nào với child31.

Do đó đề xuất của tôi sẽ liệt kê tất cả tổ tiên gần nhất và sử dụng tuple để triển khai các hoạt động đã đặt.

+0

Cảm ơn. Đối với ứng dụng của tôi, tôi sẽ giải quyết sự mơ hồ mà bạn đề cập bằng cách nhấn mạnh rằng tất cả các loại đang được xem xét chỉ có 0 hoặc một loại cơ sở. –

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