2012-11-21 1 views
6

example (regex.cpp)에서 라이브러리 작성자는 custom struct (magic_number) 및이 struct에 대한 유효성 검사 함수를 작성하여 사용자 정의 struct를 프로그램 옵션에 통합하는 방법을 보여줍니다. 그의 예제를 따라 사용자 정의 클래스 (MyClass)에 대한 유효성 검사 함수를 작성했습니다. 컴파일러는 MyClass에 lexical_cast를 사용할 수 없다고 불평합니다. 그런 다음 std::istream& operator>>(std::istream& in, MyClass& d)을 구현하고 void validate(.., MyClass*, ..)을 제거하면 코드가 컴파일됩니다. 누구든지 operator>>을 필요로하지 않는 이유를 설명 할 수 있습니까? 광산에는 validate이 필요하지 않습니다.프로그램 옵션 올리기 : 사용자 정의 유효성 검사기에 과부하 연산자가 필요합니까 >>?

편집 :

#include <MyLib/MyClass.h> 

std::istream& operator>>(std::istream& in, MyClass& obj) { 
    // some code to populate obj 
    return in; 
} 


po::variables_map parseCommandLine(int argc, char* argv[]) { 

    po::options_description options("Options"); 
    options.add_options() 
     ("help", "produce help message") 
     ("obj", po::value<MyClass>(), "") 
     ; 
    po::variables_map vm; 
    store(po::command_line_parser(argc, argv) 
     .options(options).run(), vm); 
    notify(vm); 

    return vm; 
} 

int main(int argc, char* argv[]) { 

    try { 
     po::variables_map vm = parseCommandLine(argc, argv); 

     MyClass obj = vm["my"].as<MyClass>(); 

     cout << obj << endl; 
    } catch(std::exception& e) { 
     cout << e.what() << "\n"; 
     return 1; 
    } 
    return 0; 
} 
  • 코드의 유효성을 검사하지 않고 컴파일합니다.

    1. 제거 magic_number
    2. #include <MyLib/MyClass.h>
    3. 가 MyClass에 의해 magic_number의 모든 occurance을 대체 추가

는 또한 regex.cpp에 최소한의 변경을 시도했다.

  • 유효성 검사에서 모든 코드를 주석으로 처리하십시오.
  • 이것은 컴파일되지 않습니다.
  • 편집 : validate을 추가하십시오. 그들 중 누구도 컴파일러 오류를 해결하지 못했습니다.

    void validate(boost::any& v, 
           const std::vector<std::string>& values, 
           std::vector<MyClass>*, int) 
    { 
    } 
    
    void validate(boost::any& v, 
           const std::vector<std::string>& values, 
           MyClass*, long) 
    { 
    } 
    
    void validate(boost::any& v, 
           const std::vector<std::string>& values, 
           MyClass*, int) 
    {  
    } 
    

    편집 : 이것은 네임 스페이스와 관련 될 수 있습니다.

    유효성 검사 기능을 namespace boost { namespace program_options { }}으로 묶은 후에 코드에 op >>이 (가) 오버로드되지 않고 컴파일되었습니다. 또한 유효성 검사가 MyClass와 동일한 네임 스페이스에 추가 된 경우에도 작동합니다. 아무도 이것을 설명 할 수 있습니까?

    +0

    'program_options' 객체를 어떻게 선언했는지 볼 수 있습니까? 유효성 검사가 없다면'op >>'없이 객체를 파싱 할 방법이 없다. –

    +1

    이것은 컴파일러 문제입니다. http://stackoverflow.com/questions/13501598/c-the-context-of-an-unqualified-name-lookup- : [여기에 문제의 설명] [1] [1] 참조 in-a-template –

    답변

    5

    당신이 직면 한 근본적인 문제는 C++이 문자열을 임의의 사용자 객체 (임의의 코드를 작성하지 않고)로부터 보호하는 기능을 제공하지 않는다는 것입니다.

    • 당신이 그렇게하는 표준 C++ 방법 인 operator>>을 구현,하지만 당신은 구문 분석 할 수 있습니다 즉, 다른 지역에 영향을 (가지고있다 :

      문제를 해결하려면, program_options는 두 가지 가능성을 제공합니다 명령 줄을 제외하고는 특정 방법으로 개체를 가리 킵니다. 내부적으로 boost::lexical_cast은 변환을 구현하는 데 사용되며 op>>을 찾을 수없는 경우 오류가 발생합니다.

    • validate 함수를 구현합니다.이 함수는 program_options에만 해당하지만 옵션 관리 외부에는 영향을 미치지 않습니다.

    나는 validate을 제공했는지 여부를 알아 내기 위해 템플릿 메타 프로그래밍을 사용하거나, lexical_cast으로 기본 설정됩니다.

    코드를 제공하지 않아서 validate 시도가 실패한 이유를 도울 수 없습니다.

    #include <boost/program_options.hpp> 
    #include <vector> 
    #include <string> 
    
    namespace po = boost::program_options; 
    
    namespace lib { 
        class MyClass 
        { 
        public: 
         int a; 
        }; 
    
        void validate(boost::any& v, 
            const std::vector<std::string>& values, 
            MyClass*, int) 
        { 
         po::validators::check_first_occurrence(v); 
         const string& s = po::validators::get_single_string(values); 
         v = boost::any(MyClass { boost::lexical_cast<int>(s) }); 
        } 
    } 
    
    
    po::variables_map parseCommandLine(int argc, char* argv[]) 
    { 
        po::options_description options("Options"); 
        options.add_options() 
         ("help", "produce help message") 
         ("obj", po::value<lib::MyClass>(), "") 
         ; 
        po::variables_map vm; 
        store(po::command_line_parser(argc, argv) 
         .options(options).run(), vm); 
        notify(vm); 
    
        return vm; 
    } 
    
    int main(int argc, char* argv[]) 
    { 
        try { 
         po::variables_map vm = parseCommandLine(argc, argv); 
         lib::MyClass obj = vm["obj"].as<lib::MyClass>(); 
         cout << obj.a << endl; 
        } catch(std::exception& e) { 
         cout << e.what() << "\n"; 
         return 1; 
        } 
        return 0; 
    } 
    
    • 업데이트 네임 스페이스와

    , 클래스 모두 동일한 네임 스페이스에 속해 있어야합니다 확인 : 여기

    하지만, 작업 예이다.

    +0

    빈 유효성 검사 기능으로 프로그램이 컴파일되지 않았습니다. 따라서 컴파일러가 어떻게 든 유효성 검사 오버로드를 선택하지 않았고 lexical_cast를 사용하도록 기본값이 설정된 것처럼 느껴집니다. BTW, 귀하의 예제를 regex.cpp 다를 수 있습니다. –

    +2

    아마도'validate' 함수를 잘못 선언했을 것입니다.하지만 어떻게했는지 보여주지 않으면 도움이되지 않습니다. 내 샘플은 빈 유효성 검사로 잘 컴파일됩니다. –

    +0

    boost/program_options/details/value_semantic.hpp –

    관련 문제