2012-01-11 26 views

Trả lời

1

Tôi đã lướt qua tài liệu Boost.Program_options và không rõ ràng cho dù bạn có thể làm điều đó. Tôi có ấn tượng rằng thư viện chủ yếu quan tâm đến việc phân tích cú pháp phân tích cú pháp dòng lệnh, không xác thực nó. Bạn có thể làm việc gì đó với một số custom validator, nhưng điều đó liên quan đến việc ném ngoại lệ khi bạn nhận được đầu vào xấu (có thể là một lỗi nghiêm trọng hơn bạn muốn). Tôi nghĩ rằng tính năng này hướng đến việc đảm bảo bạn thực sự có một chuỗi, chứ không phải là "con mèo" hay "con chó". Giải pháp đơn giản nhất tôi có thể nghĩ là để thư viện phân tích cú pháp dòng lệnh như bình thường, sau đó thêm mã của riêng bạn sau để xác minh --arg được đặt thành cat hoặc dog. Sau đó, bạn có thể in lỗi và thoát, hoàn nguyên về một số mặc định phù hợp hoặc bất kỳ điều gì bạn thích.

17

Bạn có thể sử dụng tính năng custom validator. Xác định một loại riêng biệt cho tùy chọn của bạn, và sau đó quá tải chức năng validate trên loại đó.

struct catdog { 
    catdog(std::string const& val): 
    value(val) 
    { } 
    std::string value; 
}; 

void validate(boost::any& v, 
       std::vector<std::string> const& values, 
       catdog* /* target_type */, 
       int) 
{ 
    using namespace boost::program_options; 

    // Make sure no previous assignment to 'v' was made. 
    validators::check_first_occurrence(v); 

    // Extract the first string from 'values'. If there is more than 
    // one string, it's an error, and exception will be thrown. 
    std::string const& s = validators::get_single_string(values); 

    if (s == "cat" || s == "dog") { 
    v = boost::any(catdog(s)); 
    } else { 
    throw validation_error(validation_error::invalid_option_value); 
    } 
} 

Ngoại lệ được ném từ mã đó không khác với ngoại lệ được ném cho bất kỳ giá trị tùy chọn không hợp lệ nào khác, vì vậy bạn đã sẵn sàng để xử lý chúng.

Sử dụng các loại tùy chọn đặc biệt thay vì chỉ string khi bạn xác định lựa chọn của bạn:

desc.add_options() 
    ("help", "produce help message") 
    ("arg", po::value<catdog>(), "set animal type") 
; 

tôi đã sáng tác một live example demonstrating use of this code.

+0

Ví dụ này trông rất giống với một trong những quy định trong [tài liệu chính thức] (http://www.boost.org/doc/libs/1_55_0/doc/html/program_options/howto.html#idp163429032) . Tuy nhiên, bạn cần triển khai hàm toán tử trích xuất quá 'std :: istream & operator >> (std :: istream & in, catdog & cd)' '{' 'return in >> in.value;' '} ' ' – russoue

+1

Có, @Russoue, mã của tôi được điều chỉnh trực tiếp từ tài liệu mà tôi đã liên kết trước đó. Tôi không biết tại sao bạn nghĩ rằng mã cần khai thác luồng, mặc dù. Tôi đã bao gồm một ví dụ làm việc làm sai lệch yêu cầu của bạn. Tài liệu sử dụng 'lexical_cast' để chuyển đổi từ chuỗi đầu vào sang kiểu dữ liệu mong muốn, và nếu bạn muốn sử dụng cùng một kỹ thuật đó, thì bạn sẽ thực sự cần phải thực hiện' toán tử >> '. Ví dụ của tôi sử dụng xây dựng trực tiếp, mặc dù. * Cách * để tạo kiểu tùy chỉnh từ một chuỗi nằm ngoài phạm vi của câu hỏi này. –

5

Cách tiếp cận rất đơn giản là có "động vật" như một chuỗi bình thường và sau khi thông báo cho bạn kiểm tra và ném nếu cần.

if (vm.count("animal") && (!(animal == "cat" || animal == "dog"))) 
     throw po::validation_error(po::validation_error::invalid_option_value, "animal"); 
+0

Đây không phải là những gì Michael đề xuất? –

+0

@RobKennedy Ngoại trừ việc Michael nói "Đây là những gì bạn có thể làm", trong khi jorgen nói "Đây là những gì bạn có thể làm, và đây là cách nó sẽ trông như thế nào" –

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