代码之家  ›  专栏  ›  技术社区  ›  zayd

在C中Boost程序选项创建的矢量上迭代++

  •  0
  • zayd  · 技术社区  · 1 年前

    我是C++的新手,正在尝试使用Boost的program_options头创建 vector<string> 位置选项,但无论我做什么,我似乎都无法实际做任何事情或迭代它们。我目前正在编译GCC 14.1.1上的C++23。

    我目前正在使用此选项:

    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;
          |          ^~~
    

    当我尝试创建一个新的 向量<字符串> 使用参数,我还得到了一个关于转换的错误 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");
          |                          ~~~~~~~~^~~~~~~~
    

    此外,我的问题被标记为重复,链接 this one 。我的问题是专门关于向量的,而链接的问题不是。该线程中给出的答案似乎没有任何明显的方法来调整它们以适应我想要做的事情,除非我在这里遗漏了一些东西(考虑到我几乎不知道我在用这种语言做什么,我不会否认这种可能性)。

    1 回复  |  直到 1 年前
        1
  •  0
  •   sehe    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;
    

    Live On Coliru

    #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