Перебор векторов, созданных опциями программы Boost на C++

Я новичок в 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");
      |                          ~~~~~~~~^~~~~~~~

Кроме того, мой вопрос был помечен как дубликат со ссылкой на этот. Мой вопрос конкретно о векторах, а тот, который связан, - нет. Ответы, данные в этой теме, похоже, не имеют какого-либо очевидного способа адаптировать их к тому, что я хочу сделать, если только я здесь что-то не упускаю (возможность чего я не отрицаю, учитывая, что у меня почти нет идея, что я делаю с этим языком).

моя программа не компилируется. Говорится ли там: «Я ваша программа, я не компилирую». Или это вызывает более адекватную ошибку, которую вы не хотите нам показывать? Что такое ЛСП?

3CxEZiVlQ 27.05.2024 01:51

Здесь тоже выдает ошибку о конвертации. Не пытайтесь пересказать сообщение об ошибке, опубликуйте его дословно.

3CxEZiVlQ 27.05.2024 01:52

@273K Это не обман. Код вопроса более чем достаточен, чтобы показать проблему. На самом деле проблема не связана с /итерацией/ вектора, а скорее с /получением/ диапазона.

sehe 27.05.2024 03:03

Не уверен, отображается ли это у всех остальных (я писал здесь один раз несколько лет назад в другом аккаунте), но я обновил вопрос, добавив дополнительную информацию и журналы. Извините, что не включил это в начало.

zayd 27.05.2024 03:06

@273K :waves: здравствуйте, возможно, удалили дурацкое голосование? Я никогда не знаю, как решить подобные проблемы, поэтому, если бы вы это сделали, я был бы рад узнать. В противном случае обычно проводится только голосование за повторное открытие, но на самом деле это работает примерно раз в 3 года.

sehe 27.05.2024 03:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема не столько в итерациях, сколько в доступе к вектору. Карта переменных содержит 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

Это был правильный обман, но вы снова открыли вопрос, чтобы опубликовать собственный ответ.

3CxEZiVlQ 27.05.2024 08:25

@273K итерация карты переменных сильно отличается от использования из нее типизированного элемента. Обман исчез до того, как я снова открыл его, а также потребовался всего один щелчок, что не то, к чему я привык (похоже, что обычно требуется как минимум 3 или 5 повторных открытий). Возможно, задействована новая функция. В любом случае спасибо за добавление вашей информации!

sehe 27.05.2024 09:27

Другие вопросы по теме