2013-07-12 28 views
5

Tôi đang sử dụng xsd để tạo mã c + + từ tệp sơ đồ xml. Đối với một loại xml nhiều chức năng được tạo ra (cho serialization vv).
Nếu loại được gọi là XmlType nhiều chức năng của các hình thức sau đây được tạo ra:nhiều chức năng có cùng tên nhưng các loại đối số khác nhau như tham số mẫu

XmlType XmlType_(const XmlType& a, const string& b) 
string XmlType_(const XmlType& a) 
... 

Đây là chức năng bình thường và không thành viên của XmlType và tất cả họ đều có cùng tên. Đối với XmlType2, các chức năng sẽ được gọi là XmlType2_.

Tôi muốn viết một lớp mẫu tiện ích cho tất cả các loại xml khác nhau của lược đồ xml của tôi. Các chức năng khác nhau sẽ được gọi là cái nhìn sâu sắc lớp này. Những gì tôi có cho đến nay là một cái gì đó như thế này:

template<typename T> 
using TFunc1 = T (*)(const T&, const string&); 
template<typename T> 
using TFunc2 = string (*)(const T&); 

template<typename T, TFunc1<T> func2, TFunc2<T> func2> 
class XmlUtil { 
... 
}; 

Khi tạo một thể hiện của các XmlUtil lớp nếu phải làm điều đó như thế này:

XmlUtil<XmlType, XmlType_, XmlType_> util; 

này cảm thấy một chút dư thừa và trở nên tồi tệ hơn , khi tôi phải chuyển nhiều hàm hơn làm tham số.

Tôi muốn sử dụng lớp util như thế này:

XmlUtil<XmlType, XmlType_> util; 

hoặc thậm chí tốt hơn như thế này

XmlUtil<XmlType> util; 

Cách duy nhất tôi có thể nghĩ là bằng cách nào đó sử dụng xác định, nhưng nó doesn không cảm thấy đúng.
Có cách nào khác để thực hiện việc này không?

EDIT: Tôi đang sử dụng một định nghĩa bây giờ:

#define TRPL(name) name, name ## _, name ## _ 
... 
XmlUtil<TRPL(XmlType)> util; 

tôi sẽ chỉnh sửa này, nếu tôi tìm thấy một cái gì đó tốt hơn (có thể ghi đè lên bộ như Yakk gợi ý trong câu trả lời của mình).

+0

Đây là C++ 11 cụ thể, tôi tin? –

+0

Có, tôi đang sử dụng C++ 11 (MinGW với gcc 4.8). Đã thêm thẻ. – guini

+0

chuyên môn về mẫu. Thực hiện tương đương với Func <> (trong C#) trong C++ bằng cách sử dụng nó trong đó Execute có một tham số mẫu thực hiện cụ thể và đếm đối số. Bằng cách sử dụng các thiết lập mặc định trong mẫu bạn có thể chọn để chỉ định nghĩa một số đối số kiểu. –

Trả lời

3

này:

XmlUtil<XmlType> util; 

là không thể bởi vì không có cách nào để có được XmlType-XmlType_. Mối quan hệ của họ bị loại bỏ sau khi bộ tạo mã tự động.

Tuy nhiên điều này:

XmlUtil<XmlType_> util; 

có thể thực hiện được. Bạn có thể suy ra loại chức năng của XmlType_ và sau đó sử dụng loại trả về được suy ra sẽ là XmlType. Tôi tin rằng có chức năng thư viện chuẩn cho mục đích này.

Đối với hai lần quá tải khác nhau, điều này có thể phức tạp hơn. Tôi không nghĩ rằng bạn có thể vượt qua một quá tải chức năng thiết lập như là một tham số mẫu, độ phân giải được thực hiện trên đối số mẫu trong bối cảnh của tham số mẫu cho một chức năng. Tôi không nghĩ rằng có một cách để trì hoãn hành động này mà không sử dụng bộ tiền xử lý.

Vì vậy, tôi cho rằng bạn nên sử dụng số #define. Nó tốt hơn là không có gì.

0

Đối số mẫu mặc định trong định nghĩa lớp?

Giống như

template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_> 
class XmlUtil { 
    // ... 
}; 
+0

Tên của hàm phụ thuộc vào tên kiểu. Vì vậy, tôi nghĩ rằng điều này sẽ không hoạt động. Tôi đã chỉnh sửa câu hỏi để làm rõ hơn. – guini

+1

@guini Tôi vừa thử nó, và [nó có vẻ biên dịch tốt] (http://ideone.com/fu5s8M). Giá trị một shot để thử? –

+0

Nếu tôi hiểu chính xác tên hàm XmlType_ được sửa trong ví dụ của bạn. Nhưng trong trường hợp của tôi, tên hàm thay đổi. Nếu tôi có loại Type1, hàm này sẽ được gọi là Type1_, đối với Type2, nó sẽ được gọi là Type2_, v.v. – guini

0

Bạn có thể sử dụng một lớp đặc điểm như thế này

template <typename T> 
struct Trait{ 
    typedef T type; 
    typedef T (*func1)(const T&, const string&); 
    typedef string (*func2)(const T&); 
}; 

và làm cho lớp XmlUtil có một mẫu tham số (chúng ta hãy đặt tên cho nó Trait) và sử dụng Trait :: loại, Trait :: func1 và Trait :: func2. Xem here để sử dụng đầy đủ.

Trong ví dụ, các loại XmlUtil đi như thế:

XmlUtil<Trait<XmlType> > 

tôi đã thực hiện nó theo cách này vì tôi không biết rõ vấn đề của bạn.Có thể là trường hợp bạn chỉ có thể xác định lớp Trait ngay vào XmlUtil và sử dụng

XmlUtil<XmlType> 

Các biến thể khác có thể, nó chỉ phụ thuộc vào những gì bạn cần.

Bạn có thể đọc phần giới thiệu ngắn về các lớp đặc điểm here. Nếu bạn muốn đọc thêm về chủ đề này, tôi đề nghị bạn Modern C++ (Alexandrescu).

+0

Cảm ơn câu trả lời của bạn. Tôi sẽ kiểm tra. Nhưng tôi sẽ cần một chút thời gian để hiểu nó :-) – guini

+0

Tôi đã thay đổi liên kết mã, tôi đã đặt một số nhận xét ở đó –

+0

Đọc lại câu hỏi và câu trả lời Tôi không chắc chắn tôi đã giải quyết câu hỏi của bạn đúng cách, cung cấp cho tôi một số phản hồi để tôi có thể giúp đỡ nhiều hơn, nếu cần. –

0

Tôi không chắc tôi hoàn toàn hiểu những gì bạn đang yêu cầu. Cách tiếp cận chung để tuần tự hóa và deserialization sẽ là tạo ra một nhà máy (nhà máy trừu tượng) và giải quyết việc xây dựng các đối tượng động. Lưu ý rằng điều này có thể được cải thiện cho các cấu trúc phức tạp, trong đó trình tạo mã có thể tạo các hàm thành viên để trích xuất loại chính xác của từng thành viên.

Nhưng một lần nữa, tôi không hoàn toàn hiểu những gì bạn đang thực sự cố gắng làm ... Tôi khuyên bạn nên tin rằng nếu bạn cung cấp thêm mô tả về vấn đề cần giải quyết, thì câu hỏi tập trung vào cách thức để làm cho giải pháp của bạn hoạt động và loại bỏ hoàn toàn các cách tiếp cận khác có thể là thiết kế tốt hơn.

1

Điều này trông giống như một công việc cho bộ ghi đè.

static struct foo_override_set_type { 
    template<typename... Args> 
    auto operator()(Args...&& args) const 
    -> 
    decltype(foo(std::forward<Args>(args)...)) 
    { return (foo(std::forward<Args>(args)...)); } 
    template<typename T> 
    operator T() { return foo; } 
} foo_override_set; 

Đối tượng loại foo_override_set_type đại diện cho toàn bộ bộ ghi đè foo. Gọi cho họ bằng operator() sẽ thực hiện tra cứu bộ ghi đè trên foo và gọi hàm kết quả. Việc đưa chúng vào một con trỏ hàm sẽ thực hiện tương tự như việc truyền mã thông báo foo tới một con trỏ hàm (hoặc giá trị khác).

Tạo mã của bạn có thể tự động tạo các loại bộ ghi đè như vậy. Nó cũng có thể tạo ra một đặc điểm lớp bản đồ từ loại XmlType của bạn để ghi đè các chức năng XmlType_ thông qua chuyên môn.

Sau đó, XmlUtil<XmlType> của bạn có thể truy cập bộ ghi đè XmlType_ thông qua lớp đặc điểm đó. Đầu tiên nó khởi tạo biến tập hợp ghi đè, sau đó gọi () trên đó.

Ngoài ra, @Xeo có đề xuất tạo các đối tượng dễ dàng như nhập []XmlType_ trong C++ 1y hoặc C++ 1z.

+0

Cảm ơn bạn đã đề xuất. Tôi chưa hiểu hết, nhưng tôi sẽ xem xét nó. Bạn có thể có một liên kết đến một số tài liệu về bộ ghi đè không? – guini

+1

@guini Không, không hẳn. Một bộ ghi đè chỉ là một đối tượng cư xử "như thể" nó là một tập hợp đầy đủ các ghi đè của một số tên hàm cú pháp. Bạn có thể làm điều này với sự chuyển tiếp hoàn hảo và một toán tử 'template T' khá tốt. Bạn có thể đọc về chuyển tiếp hoàn hảo (kỹ thuật C++ 11 mà tôi sử dụng ở trên trong 'operator()') có thể làm cho nó có ý nghĩa hơn. 'Toán tử T' tồn tại để bạn có thể gán một bộ ghi đè lên một con trỏ hàm và có nó trích xuất thuộc tính" phép thuật ". Và bởi vì nó là một đối tượng không trạng thái, bạn có thể vượt qua nó hoặc loại của nó đến nơi bạn cần. – Yakk

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