【问题标题】:Custom validator for boost program_options doesn't work with GCC, works with MSVCboost program_options 的自定义验证器不适用于 GCC,但适用于 MSVC
【发布时间】:2014-11-21 23:29:55
【问题描述】:

假设我想对整数选项进行特殊处理。根据文档,我必须编写自己的验证函数。考虑以下短程序。

#include <iostream>
#include <vector>
#include <string>

#include <boost/program_options.hpp>

namespace po = boost::program_options;

namespace boost { namespace program_options {
template <class charT>
void validate(boost::any& v, const std::vector<std::basic_string<charT> >& xs, unsigned int*, int)
{
    std::cout << "validate is redefined" << std::endl;
    // do something else
}
}}

int main(int argc, char* argv[])
{
    po::options_description cmdLineOptions;
    po::variables_map vm;

    unsigned int v;
    const char* args[] = {"tst", "-k", "10"};

    cmdLineOptions.add_options()
        ("key,k", po::value<unsigned int>(&v)->required())
      ;

    po::store(po::command_line_parser(sizeof(args) / sizeof(args[0]), args).options(cmdLineOptions).run(), vm);
    po::notify(vm);

    std::cout << v << '\n';

    return 0;
}

它在 VS 2013 中完美运行并输出

validate is redefined
10

在 GCC 中,它从不进入 validate 函数。

证明:http://coliru.stacked-crooked.com/a/fd558ebf987a4bbe

如果我尝试使用自定义类型而不是 unsigned int,GCC 无论如何都会尝试使用来自 program_option 的验证,最终会出现一堆错误。

我做错了什么?

【问题讨论】:

    标签: c++ boost boost-program-options


    【解决方案1】:

    初步预感,考虑使用

    BOOST_STRONG_TYPEDEF(unsigned int, Unsigned);
    

    只在内置类型上自定义行为似乎是个坏主意。


    解决方案:它与偏序有关。

    如果您将重载移到 boost::program_options 命名空间之外,它将开始工作(因为它不再与基本模板竞争)。

    Live On Coliru

    #include <iostream>
    #include <vector>
    #include <string>
    
    #include <boost/any.hpp>
    #include <boost/serialization/strong_typedef.hpp>
    #include <boost/program_options.hpp>
    
    BOOST_STRONG_TYPEDEF(unsigned, Unsigned)
    
    template<class charT>
        void validate(boost::any& v, 
                const std::vector< std::basic_string<charT> >& xs, 
                Unsigned* p, int)
        {
            std::cout << "validate is redefined" << std::endl;
            // do something else
        }
    
    namespace po = boost::program_options;
    
    int main()
    {
        po::options_description cmdLineOptions;
        po::variables_map vm;
    
        Unsigned v;
        const char* args[] = {"tst", "-k", "10"};
    
        cmdLineOptions.add_options()
            ("key,k", po::value<Unsigned>(&v)->required())
          ;
    
        po::store(po::command_line_parser(sizeof(args) / sizeof(args[0]), args).options(cmdLineOptions).run(), vm);
        po::notify(vm);
    
        std::cout << v << '\n';
    
        return 0;
    }
    

    原因可能是 MSVC 著名的损坏的两阶段查找

    【讨论】:

    • 感谢您的解决方法。是的,似乎在 GCC 中部分排序被破坏了。
    • @noxmetus 我还不相信。 Clang 也是如此。这可能是可以记录得更好的东西......
    • 这个变通方法并不是很有用,因为通常人们想在验证器中调用 check_first_occurrence 和 get_single_string 并且它们是在 program_options 头文件中定义的。
    • 这并不是一种解决方法。我正在解决问题并分享我的想法:)
    • “只在内置类型上自定义行为似乎是个坏主意” 首先,它没有任何问题。其次,引用我的帖子:“如果您尝试使用自定义类型而不是 unsigned int,GCC 无论如何都会尝试使用来自 program_option 的验证,最终会出现一堆错误”。
    猜你喜欢
    • 2022-11-26
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多