Улучшить параметры программы: требует ли пользовательский валидатор оператора перегрузки & gt; & gt ;?

в пример (regex.cpp), автор библиотеки создал пользовательскую структуру (magic_number) и функцию проверки для этой структуры, чтобы показать, как пользовательская структура может быть интегрирована в параметры программы. Я последовал его примеру, чтобы создать функцию проверки для пользовательского класса (MyClass). Компилятор жалуется, что lexical_cast недоступен для MyClass. Я тогда реализовал 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;
}
  • код компилируется без проверки.

Я также попытался внести минимальные изменения в regex.cpp:

  1. удалить магический номер
  2. добавлять #include <MyLib/MyClass.h>
  3. замените все вхождения magic_number на MyClass.
  4. закомментируйте весь код в validate.
  5. Это не компилируется.

РЕДАКТИРОВАТЬ: добавить 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 >>. Это также работает, если validate помещается в то же пространство имен, что и MyClass. Кто-нибудь может объяснить это?

7

Решение

Основная проблема, с которой вы сталкиваетесь, заключается в том, что C ++ не предлагает никаких средств для сохранения строки в произвольном пользовательском объекте (я имею в виду без написания какого-либо кода).

Чтобы решить эту проблему, program_options предлагает две возможности:

  • вы реализуете operator>>, который является стандартным способом C ++, но может оказать влияние на некоторые другие области (т. е. вы можете захотеть проанализировать ваш объект определенным образом, кроме как в командной строке). Внутренне 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;
}
  • Обновить

С пространством имен и класс, и validate должны принадлежать одному пространству имен.

5

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector