2012-11-21 7 views
6

W bibliotece example (regex.cpp) autor biblioteki utworzył niestandardową strukturę (magic_number) i funkcję sprawdzania poprawności tej struktury, aby pokazać, w jaki sposób niestandardową strukturę można zintegrować z opcjami programu. Podążyłem za jego przykładem, aby utworzyć funkcję sprawdzania poprawności dla niestandardowej klasy (MyClass). Compiler narzeka, że ​​leksykalny_cast nie jest dostępny dla MyClass. Następnie zaimplementowałem std::istream& operator>>(std::istream& in, MyClass& d), usunięto void validate(.., MyClass*, ..), kod kompiluje. Czy ktoś może wyjaśnić, dlaczego przykład nie wymaga operator>>, a mój nie wymaga validate?opcje programu boost: czy niestandardowy weryfikator wymaga operatora przeciążającego >>?

EDIT:

#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; 
} 
  • kod kompiluje bez sprawdzenia poprawności.

Próbowałem też dokonywania minimalnej zmianie do regex.cpp:

  1. usuń magic_number
  2. dodać #include <MyLib/MyClass.h>
  3. zastąpić wszystkie występowaniu gazów magic_number przez MojaKlasa.
  4. skomentuj wszystkie kody w walidacji.
  5. To nie kompiluje.

EDYCJA: dodać validate. Żadne z nich nie rozwiązało błędu kompilatora.

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) 
{  
} 

EDYCJA: Może odnosić się do przestrzeni nazw.

Po tym, jak otoczyłem funkcję sprawdzania poprawności przez namespace boost { namespace program_options { }}, kod skompilowany bez przeciążenia op >>. Działa również, gdy validate jest umieszczany w tej samej przestrzeni nazw co MyClass. Czy ktoś może to wyjaśnić?

+0

Czy możemy zobaczyć, jak zadeklarowałeś obiekt 'program_opcje'? Jeśli nie ma sprawdzania poprawności, nie można przetworzyć obiektu bez 'op >>. –

+1

To jest problem kompilatora. Zobacz [Opis problemu tutaj] [1] [1]: http://stackoverflow.com/questions/13501598/c-the-context-of-an-unqualified-name-lookup- in-a-template –

Odpowiedz

5

Podstawowym problemem, przed którym stoisz, jest to, że C++ nie oferuje żadnego obiektu do konwertowania łańcucha na dowolny obiekt użytkownika (to znaczy bez pisania jakiegokolwiek kodu).

Aby rozwiązać ten problem, program_options oferuje dwie możliwości:

  • zaimplementowaniu operator>>, który jest standardem C++ sposób robić to, ale które mogą mieć wpływ na innych obszarach (czyli może chcesz do analizowania Twój obiekt w określony sposób, z wyjątkiem linii poleceń). Wewnętrznie, boost::lexical_cast służy do realizacji konwersji i wyświetli błąd, jeśli nie zostanie znaleziony op>>.
  • Użytkownik implementuje funkcję validate, która jest specyficzna dla opcji program_programów, ale która nie ma wpływu poza zarządzanie opcjami.

Domyślam się, że używa szablonu meta programowania, aby dowiedzieć się, czy podałeś validate lub domyślnie lexical_cast.

Nie mogę ci pomóc, ponieważ twoja próba z validate nie powiodła się, ponieważ nie dostarczyłeś jej kodu.

Oto przykład działa, choć:

#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; 
} 
  • Aktualizacja

Z nazw, zarówno klasy i walidacji muszą należeć do tej samej przestrzeni nazw.

+0

Chodzi o to, że program NIE skompilował się z pustą funkcją sprawdzania poprawności. Wygląda więc na to, że kompilator w jakiś sposób nie wykrył przeciążenia sprawdzania poprawności i nie używał domyślnie funkcji lexical_cast. BTW, twój przykład nie różni się od regex.cpp. –

+2

Prawdopodobnie funkcja "validate" została uznana za niewłaściwą, ale nie mogę pomóc, jeśli nie pokazałeś mi, jak to zrobiłeś. Moja próbka kompiluje się dobrze z pustym sprawdzeniem poprawności. –

+0

Śledziłem podpisy w opcji boost/program_options/details/value_semantic.hpp –

Powiązane problemy