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

使用boost::program_options::在命名空间中使用自己的类验证

  •  1
  • wally  · 技术社区  · 7 年前

    如果 magic_number

    为什么它找不到 validate 如果目标类在命名空间中,则函数为?


    在MSVC上产生的错误是:

    Hypp(243):错误C23 38:目标类型既不是 std::istream'able或std::wistream'able。

    我和Clang也有同样的错误 here .


    测试;注释/取消注释 #define USE_NAMESPACE :

    // Copyright Vladimir Prus 2002-2004.
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE_1_0.txt
    // or copy at http://www.boost.org/LICENSE_1_0.txt)
    
    // This example shows how a user-defined class can be parsed using
    // specific mechanism -- not the iostream operations used by default.
    //
    // A new class 'magic_number' is defined and the 'validate' method is overloaded
    // to validate the values of that class using Boost.Regex.
    // To test, run
    //   
    //    regex -m 123-456
    //    regex -m 123-4567
    // 
    // The first invocation should output:
    //
    //   The magic is "456"
    //
    // and the second invocation should issue an error message.
    
    #include <boost/program_options.hpp>
    #include <boost/regex.hpp>
    #include <iostream>
    
    namespace po = boost::program_options;
    
    //#define USE_NAMESPACE
    
    #ifdef USE_NAMESPACE
    namespace ns1{
    #endif
    
    /* Define a completely non-sensical class. */
    struct magic_number {
    public:
        magic_number(int n) : n(n) {}
        magic_number() = default;
        int n;
    };
    #ifdef USE_NAMESPACE
    }
    #endif
    
    /* Overload the 'validate' function for the user-defined class.
       It makes sure that value is of form XXX-XXX 
       where X are digits and converts the second group to an integer.
       This has no practical meaning, meant only to show how
       regex can be used to validate values.
    */
    #ifdef USE_NAMESPACE
    void validate(boost::any& v, const std::vector<std::string>& values, 
        ns1::magic_number*, int)
    #else
    void validate(boost::any& v, const std::vector<std::string>& values, 
        magic_number*, int)
    #endif
    {
        static boost::regex r("\\d\\d\\d-(\\d\\d\\d)");
    
    
        // Make sure no previous assignment to 'a' was made.
        po::validators::check_first_occurrence(v);
        // Extract the first string from 'values'. If there is more than
        // one string, it's an error, and exception will be thrown.
        const std::string& s = po::validators::get_single_string(values);
    
        // Do regex match and convert the interesting part to 
        // int.
        boost::smatch match;
        if (boost::regex_match(s, match, r)) {
    #ifdef USE_NAMESPACE
            v = boost::any(
                ns1::magic_number(boost::lexical_cast<int>(match[1])));
    #else
            v = boost::any(
                magic_number(boost::lexical_cast<int>(match[1])));
    #endif
        } else {
            throw po::validation_error(po::validation_error::invalid_option_value);
        }        
    }
    
    
    int main(int ac, char* av[])
    {
        try {
            po::options_description desc("Allowed options");
            desc.add_options()
                ("help", "produce a help screen")
                ("version,v", "print the version number")
    #ifdef USE_NAMESPACE
                ("magic,m", po::
                    value<ns1::magic_number>(), "magic value (in NNN-NNN format)")
    #else
                ("magic,m", po::
                    value<magic_number>(), "magic value (in NNN-NNN format)")
    #endif
                ;
    
            po::variables_map vm;
            store(parse_command_line(ac, av, desc), vm);
    
            if (vm.count("help")) {
                std::cout << "Usage: regex [options]\n";
                std::cout << desc;
                return 0;
            }
            if (vm.count("version")) {
                std::cout << "Version 1.\n";
                return 0;
            }
            if (vm.count("magic")) {
    #ifdef USE_NAMESPACE
                std::cout << "The magic is \"" << vm["magic"].as<ns1::magic_number>().n << "\"\n";
    #else
                std::cout << "The magic is \"" << vm["magic"].as<magic_number>().n << "\"\n";
    #endif
            }
        }
        catch(std::exception& e)
        {
            std::cout << e.what() << "\n";
        }    
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Jonathan Sharman    7 年前

    定义 validate() ns1 命名空间允许它编译(或移动 magic_number 验证() .

    验证() boost::program_options 被认为是比全局重载更好的匹配,但比在与 幻数 . 也许如果我错了,有人更了解C++名称查找规则。