2009-03-29 31 views
5

Khi sử dụng macro BOOST_SERIALIZATION_NVP để tạo cặp giá trị tên cho tuần tự hóa XML, trình biên dịch vui vẻ cho phép mã sau biên dịch, mặc dù tên phần tử không phải là XML hợp lệ phần tử và một trường hợp ngoại lệ được ném khi cố gắng thực sự serialize các đối tượng thành XML:tăng tuần tự hóa các macro NVP macro và các phần tử không phải là thành phần XML

BOOST_SERIALIZATION_NVP(_member[index]) 

một sửa chữa rõ ràng là sử dụng:

boost::serialization::make_nvp("ValidMemberName", _member[index]) 

Nhưng bất cứ ai có thể đề nghị một cách để sửa đổi thúc đẩy để yếu tố bất hợp pháp tên sẽ kích hoạt một compilatio n lỗi? (Do đó không dựa vào kiểm tra đơn vị để bắt lỗi tinh tế trên)


Edit:

Một ý tưởng là bằng cách nào đó khai báo một biến địa phương giả với tên của các yếu tố truyền cho vĩ mô, giả định tập hợp các số nhận dạng hợp lệ trong C++ là một tập hợp con các phần tử XML hợp lệ. Không chắc chắn toàn bộ điều này có thể được thực hiện mặc dù.

+0

Điều này sẽ tạo ra lỗi thời gian chạy 'what(): Tên thẻ XML không hợp lệ ' – alfC

Trả lời

1

Tôi nghĩ ý tưởng của bạn có thể sẽ hoạt động. Các định danh C++ hợp lệ được tạo thành từ A-Z, a-z, 0-9 và dấu gạch dưới, thực tế là một tập hợp con các định danh XML thích hợp (thêm dấu gạch nối, dấu chấm và một chuỗi ký tự Unicode vào tập hợp).

Bạn có thể thử một cấu trúc như thế này để có được một lỗi thời gian biên dịch:

#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    { int name = 0; } ; BOOST_SERIALZATION_NVP(name) 

Các niềng răng giới hạn phạm vi của biến giả để chỉ dòng đó, do đó bạn không lộn xộn chức năng của bạn với các biến giả . Có lẽ trình biên dịch cũng tối ưu hóa biến giả, vì vậy không có chi phí thời gian chạy. Khi tôi sử dụng macro này trong đoạn mã sau, tôi nhận được error: invalid intializer:

#include "boost/serialization/nvp.hpp" 
#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    { int name = 0; } ; BOOST_SERIALIZATION_NVP(name) 

int main(int argc, char *argv[]) 
{ 
    int foo[3] = { 10, 20, 30 }; 
    int bar = 10; 
    SAFE_BOOST_SERIALIZATION_NVP(foo[0]); 
    return 0; 
} 

Nếu tôi thay foo[0] với bar trong cuộc gọi đến SAFE_BOOST_SERIALIZATION_NVP, nó biên dịch không có lỗi.

+1

Nhưng tôi không nghĩ rằng nó sẽ hoạt động khi được sử dụng trong chức năng tuần tự hóa. serialize (..) {archive & SAFE_BOOST_SER_NVP (m); } ... –

+0

@AssafLavie, bạn nói đúng, tuy nhiên sửa đổi nhỏ này (mã phụ ở cuối) dường như thực hiện công việc: '#define SAFE_BOOST_SERIALIZATION_NVP (tên) \ BOOST_SERIALIZATION_NVP (tên); {int name = 0;} ' – alfC

2

Trích dẫn cú pháp XML cho tên:

NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] 
NameChar  ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] 

tôi thấy sự khác biệt sau đây với tên C++: Dẫn đầu _ có thể được đặt trong C++, tùy thuộc vào những gì sau; dấu hai chấm, dấu chấm và dấu trừ có giá trị trong các tên XML. Các ký tự Unicode cũng có thể gây ra một số đau buồn trong C++, nhưng đó là phần lớn phụ thuộc vào việc thực thi.

Phần [# x0300- # x036F] kết hợp dấu trọng âm (dấu phụ), đây có thể là mối quan tâm bình đẳng về tên wrt.

Vì vậy, không có giải pháp nào bắt được các ký tự không phải chữ cái. < ::: /> có thể trông giống như một biểu tượng mặt cười, nhưng đó là XML được định dạng tốt. Đối với phần còn lại, ý tưởng của bạn khá ổn. Ý tưởng của Eric Melski là một nỗ lực tốt đẹp, nhưng nó chấp nhận rất nhiều ký tự không phải chữ cái. Ví dụ: foo[1], &foo, *foo, foo=0 hoặc foo,bar. Có một giải pháp thay thế tốt hơn: {using namespace name;}. Điều này sẽ chấp nhận foo::bar, nhưng đó thực sự là OK - foo :: thanh được cho phép trong XML.

+0

Nhưng nếu' name' không phải là một vùng tên, nó sẽ đưa ra một lỗi. – alfC

1

Đây là sự kết hợp giữa hai câu trả lời, @Eric Melski (chủ yếu là đúng - mã nội dung phải ở cuối define - nhưng giải pháp không đầy đủ - một số tên bị cấm không được "lọc" -) và @MSalters ' chủ yếu là chính xác (- using namespace không thể được sử dụng cho các tên không khai báo tùy ý--).

Tôi đề nghị sử dụng struct:

#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    BOOST_SERIALIZATION_NVP(name); {struct name{};} 

hoặc nguy hiểm hơn:

#undef BOOST_SERIALIZATION_NVP 
#define BOOST_SERIALIZATION_NVP(name)        \ 
    boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name); {struct name{};} 

Không cần phải nói rằng không có chi phí thời gian chạy cho việc này.

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