【问题标题】:How can Boost Program_Options handle vector of arrays?Boost Program_Options 如何处理数组向量?
【发布时间】:2019-05-01 17:05:42
【问题描述】:

在我的程序中,我需要使用 Eigen 库执行一些转换。当我使用配置文件让用户调整一些设置时,我正在寻找一种将转换集成到此配置文件中的方法。我想出了以下代码:

#include <boost\program_options.hpp>
#include <boost\log\trivial.hpp>
#include <Eigen\Geometry>

namespace po = boost::program_options;

int main(int ac, char* av[])
{
    std::vector<std::array<double, 16>> trans;

    try {
        po::options_description desc("Options");
        desc.add_options()
            ("help,h", "Produce help message")
            ("config,c", po::value<std::string>(&configPath), "Path of the config file.")
            ("trans", po::value<std::vector<std::array<double, 16>>>(&trans)->multitoken(), "Vector of 4D Transformation Matrix. Syntax: {x_11, ..., x_14, x_21, ..., x_24, ..., x_44}")
            ;

        po::variables_map vm;
        po::store(po::parse_command_line(ac, av, desc), vm);
        po::notify(vm);

        if (vm.count("help")) {
            BOOST_LOG_TRIVIAL(info) << desc;
            return EXIT_SUCCESS;
        }

        std::ifstream configFile(configPath);
        po::store(po::parse_config_file(configFile, desc), vm);
        po::notify(vm);
    }
    catch (std::exception& e) {
        BOOST_LOG_TRIVIAL(error) << "error: " << e.what();
        return EXIT_FAILURE;
    }
    catch (...) {
        BOOST_LOG_TRIVIAL(error) << "Exception of unknown type!";
        return EXIT_FAILURE;
    }

    Eigen::Affine3d transAff(Eigen::Matrix4d(trans.data()).transpose());

    // Do some stuff
}

但不幸的是,我在构建解决方案时遇到了错误。错误发生在转换的 add_options 行并说:

myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast\detail\converter_lexical.hpp(243): error C2338: Target type is neither std::istream`able nor std::wistream`able
myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast\detail\converter_lexical.hpp(270): note: see reference to class template instantiation 'boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<std::array<double,16>>>' being compiled
myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast\detail\converter_lexical.hpp(407): note: see reference to class template instantiation 'boost::detail::deduce_target_char<Target>' being compiled
        with
        [
            Target=std::array<double,16>
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast\detail\converter_lexical.hpp(464): note: see reference to class template instantiation 'boost::detail::lexical_cast_stream_traits<Source,Target>' being compiled
        with
        [
            Source=src,
            Target=std::array<double,16>
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast\try_lexical_convert.hpp(196): note: see reference to class template instantiation 'boost::detail::lexical_converter_impl<Target,src>' being compiled
        with
        [
            Target=std::array<double,16>
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\lexical_cast.hpp(41): note: see reference to function template instantiation 'bool boost::conversion::detail::try_lexical_convert<Target,Source>(const Source &,Target &)' being compiled
        with
        [
            Target=std::array<double,16>,
            Source=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp(92): note: see reference to function template instantiation 'Target boost::lexical_cast<T,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>(const Source &)' being compiled
        with
        [
            Target=std::array<double,16>,
            T=std::array<double,16>,
            Source=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp(149): note: see reference to function template instantiation 'void boost::program_options::validate<T,char>(boost::any &,const std::vector<std::string,std::allocator<_Ty>> &,T *,long)' being compiled
        with
        [
            T=std::array<double,16>,
            _Ty=std::string
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp(184): note: see reference to function template instantiation 'void boost::program_options::validate<std::array<double,16>,char>(boost::any &,const std::vector<std::string,std::allocator<_Ty>> &,std::vector<std::array<double,16>,std::allocator<std::array<double,16>>> *,int)' being compiled
        with
        [
            _Ty=std::string
        ]
myDirectory\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp(177): note: while compiling class template member function 'void boost::program_options::typed_value<std::vector<std::array<double,16>,std::allocator<_Ty>>,char>::xparse(boost::any &,const std::vector<std::string,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char>>>> &) const'
        with
        [
            _Ty=std::array<double,16>
        ]
myDirectory\myProgram\src\myProgram.cpp(91): note: see reference to class template instantiation 'boost::program_options::typed_value<std::vector<std::array<double,16>,std::allocator<_Ty>>,char>' being compiled
        with
        [
            _Ty=std::array<double,16>
        ]

我认为错误是由于我尝试这样做的方式不支持数组向量。有没有什么方法可以实现这一点,或者更智能的方式来处理这些转换?

非常感谢!

【问题讨论】:

    标签: c++ eigen stdvector boost-program-options stdarray


    【解决方案1】:

    我设法自己解决了这个问题,并进行了一些修改。如果其他人有同样的问题,我希望我能帮助他回答这个问题。

    C++ 中的数组

    在第一步中,我将所有数组更改为 std::vector,因为它具有更多功能,并且因为许多帖子不鼓励使用数组,例如 here

    使用std::string 作为内部std::vector 的临时替换

    由于向量中的向量对于程序选项来说是一项艰巨的任务(因为 multitoken 只是将元素添加到向量中并且向量层之间不能不同),我用字符串替换了内部 std::vector,所以 add_options 现在是

    std::vector<std::string> trans;
    
    try {
        po::options_description desc("Options");
        desc.add_options()
            ("help,h", "Produce help message")
            ("config,c", po::value<std::string>(&configPath), "Path of the config file.")
            ("trans", po::value<std::vector<std::string>>(&trans)->multitoken(), "Vector of 4D Transformation Matrix. Syntax: x_11 ... x_14 x_21 ... x_24 ... x_44")
            ;
    
        ...
    

    std::string 转换为std::vector&lt;double&gt;

    现在我们可以将输入的字符串转换为双精度向量,因为它们可用于创建Eigen::MatrixEigen::Vector。我从this post 的 NathanOliver 那里得到了这个想法,我就是这样使用的:

    std::vector<double> str2vec(std::string str) {
        std::vector<double> out;
        std::stringstream ss(str);
    
        double tmpVal;
        while (ss >> tmpVal)
            out.push_back(tmpVal);
    
        return out;
    }
    

    大家一起

    最后我的代码如下所示:

    #include <boost\program_options.hpp>
    #include <boost\log\trivial.hpp>
    #include <Eigen\Geometry>
    
    namespace po = boost::program_options;
    
    std::vector<double> str2vec(std::string str) {
        std::vector<double> out;
        std::stringstream ss(str);
    
        double tmpVal;
        while (ss >> tmpVal)
            out.push_back(tmpVal);
    
        return out;
    }
    
    int main(int ac, char* av[])
    {
        std::vector<std::string> transVecStr;
    
        try {
            po::options_description desc("Options");
            desc.add_options()
                ("help,h", "Produce help message")
                ("config,c", po::value<std::string>(&configPath), "Path of the config file.")
                ("transVecStr", po::value<std::vector<std::string>>(&transVecStr)->multitoken(), "Vector of 4D Transformation Matrix. Syntax: x_11 ... x_14 x_21 ... x_24 ... x_44")
                ;
    
            po::variables_map vm;
            po::store(po::parse_command_line(ac, av, desc), vm);
            po::notify(vm);
    
            if (vm.count("help")) {
                BOOST_LOG_TRIVIAL(info) << desc;
                return EXIT_SUCCESS;
            }
    
            std::ifstream configFile(configPath);
            po::store(po::parse_config_file(configFile, desc), vm);
            po::notify(vm);
        }
        catch (std::exception& e) {
            BOOST_LOG_TRIVIAL(error) << "error: " << e.what();
            return EXIT_FAILURE;
        }
        catch (...) {
            BOOST_LOG_TRIVIAL(error) << "Exception of unknown type!";
            return EXIT_FAILURE;
        }
    
        std::vector<Eigen::Affine3d> affineVec;
        for(int i = 0; i<transVecStr.size();i++){
            affineVec.emplace_back(Eigen::Matrix4d(str2vec(transVecStr[i]).data()).transpose());
        }
    
        // Do some stuff
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多