Я новичок в C++ и пытаюсь использовать заголовок program_options Boost для создания vector<string> позиционных параметров, но что бы я ни делал, я не могу ничего сделать или перебрать их. В настоящее время я компилирую C++23 на GCC 14.1.1.
В настоящее время я использую это для вариантов:
po::options_description desc("Testing");
desc.add_options()
("help", "produce help message")
("path,p", po::value< vector<string> >(),
"Path of directory/file");
po::positional_options_description p;
p.add("path", -1);
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).
options(desc).positional(p).run(), vm);
po::notify(vm);
Я попробовал перебрать его с помощью такого цикла for, получил ошибку LSP (clangd), и моя программа не компилировалась:
if (vm.count("path")) {
for (auto i : vm.count("path")) {
cout << "Paths are: "
<< i << endl;
}
}
ошибка clangd: Invalid range expression of type 'std::map<std::basic_string<char>, boost::program_options::variable_value>::size_type' (aka 'unsigned long'); no viable 'begin' function available
Ошибка GCC:
/home/main/projects/cpp-testing/src/new.cpp: In function ‘int main(int, char**)’:
/home/main/projects/cpp-testing/src/new.cpp:26:34: error: ‘begin’ was not declared in this scope
26 | for (auto i : vm.count("path")) {
| ^
/home/main/projects/cpp-testing/src/new.cpp:26:34: note: suggested alternatives:
In file included from /usr/include/c++/14.1.1/string:53,
from /usr/include/c++/14.1.1/bits/locale_classes.h:40,
from /usr/include/c++/14.1.1/bits/ios_base.h:41,
from /usr/include/c++/14.1.1/ios:44,
from /usr/include/c++/14.1.1/ostream:40,
from /usr/include/c++/14.1.1/iostream:41,
from /home/main/projects/cpp-testing/src/new.cpp:1:
/usr/include/c++/14.1.1/bits/range_access.h:114:37: note: ‘std::begin’
114 | template<typename _Tp> const _Tp* begin(const valarray<_Tp>&) noexcept;
| ^~~~~
In file included from /usr/include/c++/14.1.1/string_view:56,
from /usr/include/c++/14.1.1/bits/basic_string.h:47,
from /usr/include/c++/14.1.1/string:54:
/usr/include/c++/14.1.1/bits/ranges_base.h:487:47: note: ‘std::ranges::_Cpo::begin’
487 | inline constexpr ranges::__access::_Begin begin{};
| ^~~~~
In file included from /usr/include/boost/range/functions.hpp:18,
from /usr/include/boost/range/iterator_range_core.hpp:38,
from /usr/include/boost/lexical_cast.hpp:48,
from /usr/include/boost/program_options/value_semantic.hpp:14,
from /usr/include/boost/program_options/options_description.hpp:13,
from /usr/include/boost/program_options.hpp:15,
from /home/main/projects/cpp-testing/src/new.cpp:3:
/usr/include/boost/range/begin.hpp:110:61: note: ‘boost::range_adl_barrier::begin’
110 | inline BOOST_DEDUCED_TYPENAME range_iterator<const T>::type begin( const T& r )
| ^~~~~
In file included from /usr/include/c++/14.1.1/bits/stl_iterator_base_types.h:71,
from /usr/include/c++/14.1.1/bits/stl_construct.h:61,
from /usr/include/c++/14.1.1/bits/char_traits.h:57,
from /usr/include/c++/14.1.1/ios:42:
/usr/include/c++/14.1.1/bits/iterator_concepts.h:983:10: note: ‘std::ranges::__access::begin’
983 | void begin() = delete;
| ^~~~~
/home/main/projects/cpp-testing/src/new.cpp:26:34: error: ‘end’ was not declared in this scope
26 | for (auto i : vm.count("path")) {
| ^
/home/main/projects/cpp-testing/src/new.cpp:26:34: note: suggested alternatives:
/usr/include/c++/14.1.1/bits/range_access.h:116:37: note: ‘std::end’
116 | template<typename _Tp> const _Tp* end(const valarray<_Tp>&) noexcept;
| ^~~
/usr/include/c++/14.1.1/bits/ranges_base.h:488:45: note: ‘std::ranges::_Cpo::end’
488 | inline constexpr ranges::__access::_End end{};
| ^~~
In file included from /usr/include/boost/range/functions.hpp:19:
/usr/include/boost/range/end.hpp:104:61: note: ‘boost::range_adl_barrier::end’
104 | inline BOOST_DEDUCED_TYPENAME range_iterator<const T>::type end( const T& r )
| ^~~
/usr/include/c++/14.1.1/bits/ranges_base.h:138:10: note: ‘std::ranges::__access::end’
138 | void end() = delete;
| ^~~
Когда я вместо этого пытаюсь создать новый vector<string> с аргументом, я также получаю сообщение об ошибке преобразования из std::map<std::basic_string<char>, boost::program_options::variable_value>::size_type.
vector<string> paths = vm.count("path");
ошибка clangd: No viable conversion from 'std::map<std::basic_string<char>, boost::program_options::variable_value>::size_type' (aka 'unsigned long') to 'vector<std::string>' (aka 'vector<basic_string<char>>)
Ошибка GCC:
/home/main/projects/cpp-testing/src/new.cpp: In function ‘int main(int, char**)’:
/home/main/projects/cpp-testing/src/new.cpp:25:34: error: conversion from ‘std::map<std::__cxx11::basic_string<char>, boost::program_options::variable_value>::size_type’ {aka ‘long unsigned int’} to non-scalar type ‘std::vector<std::__cxx11::basic_string<char> >’ requested
25 | vector<string> paths = vm.count("path");
| ~~~~~~~~^~~~~~~~
Кроме того, мой вопрос был помечен как дубликат со ссылкой на этот. Мой вопрос конкретно о векторах, а тот, который связан, - нет. Ответы, данные в этой теме, похоже, не имеют какого-либо очевидного способа адаптировать их к тому, что я хочу сделать, если только я здесь что-то не упускаю (возможность чего я не отрицаю, учитывая, что у меня почти нет идея, что я делаю с этим языком).
Здесь тоже выдает ошибку о конвертации. Не пытайтесь пересказать сообщение об ошибке, опубликуйте его дословно.
@273K Это не обман. Код вопроса более чем достаточен, чтобы показать проблему. На самом деле проблема не связана с /итерацией/ вектора, а скорее с /получением/ диапазона.
Не уверен, отображается ли это у всех остальных (я писал здесь один раз несколько лет назад в другом аккаунте), но я обновил вопрос, добавив дополнительную информацию и журналы. Извините, что не включил это в начало.
@273K :waves: здравствуйте, возможно, удалили дурацкое голосование? Я никогда не знаю, как решить подобные проблемы, поэтому, если бы вы это сделали, я был бы рад узнать. В противном случае обычно проводится только голосование за повторное открытие, но на самом деле это работает примерно раз в 3 года.





Ваша проблема не столько в итерациях, сколько в доступе к вектору. Карта переменных содержит boost::any объектов.
Вы можете получить фактическое значение с карты следующим образом:
if (vm.count("path")) {
auto& v = vm["path"].as<std::vector<std::string>>();
После этого вы можете повторить это, как вы пытались:
for (auto& s : v)
std::cout << "Path: " << s << std::endl;
#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
po::options_description desc("Testing");
desc.add_options() //
("help", "produce help message") //
("path,p", po::value<std::vector<std::string>>(), //
"Path of directory/file") //
;
po::positional_options_description p;
p.add("path", -1);
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << std::endl;
return 1;
}
if (vm.count("path")) {
auto& v = vm["path"].as<std::vector<std::string>>();
for (auto& s : v)
std::cout << "Path: " << s << std::endl;
} else {
std::cout << "Path not set" << std::endl;
}
}
Распечатки:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_{program_options,filesystem}
./a.out -p a -p b --path "c and d"
Path: a
Path: b
Path: c and d
Это был правильный обман, но вы снова открыли вопрос, чтобы опубликовать собственный ответ.
@273K итерация карты переменных сильно отличается от использования из нее типизированного элемента. Обман исчез до того, как я снова открыл его, а также потребовался всего один щелчок, что не то, к чему я привык (похоже, что обычно требуется как минимум 3 или 5 повторных открытий). Возможно, задействована новая функция. В любом случае спасибо за добавление вашей информации!
моя программа не компилируется. Говорится ли там: «Я ваша программа, я не компилирую». Или это вызывает более адекватную ошибку, которую вы не хотите нам показывать? Что такое ЛСП?