boost - 如何使用 boost::program_options 解析逗号分隔值?

标签 boost command-line boost-program-options

我需要使用 boost::program_options-value=str1,str2,str3 一样解析 cmd。我找到了 exactly the same question但它不再工作了( boost 1.55 和 1.56)。

我尝试定义自己的类和映射器,但没有成功:

namespace po = boost::program_options;

desc.add_options()
        ("mattr", po::value<lli::CommaSeparatedVector>(&MAttrs), "Target specific attributes (-mattr=help for details)");

namespace lli {
  class CommaSeparatedVector 
  {
      public:
        // comma separated values list
        std::vector<std::string> values;
  };
}

void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = ",")
{
  // Skip delimiters at beginning.
  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);

  // Find first non-delimiter.
  std::string::size_type pos = str.find_first_of(delimiters, lastPos);

  while (std::string::npos != pos || std::string::npos != lastPos) {
    // Found a token, add it to the vector.
    tokens.push_back(str.substr(lastPos, pos - lastPos));

    // Skip delimiters.
    lastPos = str.find_first_not_of(delimiters, pos);

    // Find next non-delimiter.
    pos = str.find_first_of(delimiters, lastPos);
  }
}

// mapper for "lli::CommaSeparatedVector"
std::istream& operator>>(std::istream& in, lli::CommaSeparatedVector &value)
{
    std::string token;
    in >> token;

    tokenize(token, value.values);

    return in;
}

错误信息:

In file included from /softdev/boost-1.56/include/boost/program_options.hpp:15:
In file included from /softdev/boost-1.56/include/boost/program_options/options_description.hpp:13:
In file included from /softdev/boost-1.56/include/boost/program_options/value_semantic.hpp:14:
/softdev/boost-1.56/include/boost/lexical_cast.hpp:379:13: error: implicit instantiation of undefined template
      'boost::STATIC_ASSERTION_FAILURE<false>'
            BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value), 
            ^
/softdev/boost-1.56/include/boost/static_assert.hpp:36:48: note: expanded from macro 'BOOST_STATIC_ASSERT_MSG'
#     define BOOST_STATIC_ASSERT_MSG( B, Msg ) BOOST_STATIC_ASSERT( B )
                                               ^
/softdev/boost-1.56/include/boost/static_assert.hpp:169:13: note: expanded from macro 'BOOST_STATIC_ASSERT'
            sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( __VA_ARGS__ ) >)>\
            ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:406:44: note: in instantiation of template class
      'boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<lli::CommaSeparatedVector> >'
      requested here
            typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
                                           ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:564:59: note: in instantiation of template class
      'boost::detail::deduce_target_char<lli::CommaSeparatedVector>' requested here
            typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char<Target>::type target_char_t;
                                                          ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2067:40: note: in instantiation of template class
      'boost::detail::lexical_cast_stream_traits<std::__1::basic_string<char>, lli::CommaSeparatedVector>' requested here
                BOOST_DEDUCED_TYPENAME stream_trait::char_type,
                                       ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2289:20: note: in instantiation of template class
      'boost::detail::lexical_converter_impl<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested here
            return caster_type::try_convert(arg, result);
                   ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2316:41: note: in instantiation of function template specialization
      'boost::conversion::detail::try_lexical_convert<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested
      here
        if (!boost::conversion::detail::try_lexical_convert(arg, result))
                                        ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:89:21: note: in instantiation of function
      template specialization 'boost::lexical_cast<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested here
            v = any(lexical_cast<T>(s));
                    ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:167:13: note: in instantiation of function
      template specialization 'boost::program_options::validate<lli::CommaSeparatedVector, char>' requested here
            validate(value_store, new_tokens, (T*)0, 0);
            ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:182:33: note: in instantiation of member function
      'boost::program_options::typed_value<lli::CommaSeparatedVector, char>::xparse' requested here
        typed_value<T>* r = new typed_value<T>(v);
                                ^
./lib_lli.cpp:480:23: note: in instantiation of function template specialization
      'boost::program_options::value<lli::CommaSeparatedVector>' requested here
        ("mattr", po::value<lli::CommaSeparatedVector>(&MAttrs), "Target specific attributes (-mattr=help for details)");
                      ^
/softdev/boost-1.56/include/boost/static_assert.hpp:87:26: note: template is declared here
template <bool x> struct STATIC_ASSERTION_FAILURE;
                         ^
1 warning and 1 error generated.

最佳答案

您必须使 operator>> 可被发现。

因为它需要在 std::istream& 的左侧操作,所以不能在“拥有”类中声明;但作为一项免费功能,您将需要使用 namespace 查找,以便代码找到流式处理运算符。

现在请注意,流运算符是从命名空间 boost::detail 中的某处调用的(来自 Boost Lexicalcast 库)。

它使用参数依赖查找 来选择重载。 ADL 意味着与参数类型关联的 namespace 指示应搜索哪些 namespace 以查找候选运算符 >> 重载。¹

这意味着查找将搜索命名空间 std(由于 std::istream 参数)以及 lli(由于第二个参数类型)。请注意,如果任何参数 types 本身使用 template argument 类型,则定义 that 的 namespace 也包含在查找中。

正如您所说,您可以解决这个问题

  • 不使用 namespace 。
  • 或者,您可以在lli 命名空间内定义运算符>> 重载: Live On Coliru
  • 或者,在类中声明它(作为 friend 静态函数,将被视为好像在包含的命名空间中声明): Live On Coliru

¹ 不过,它同样适用于非运算符(operator)自由功能

关于boost - 如何使用 boost::program_options 解析逗号分隔值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26389297/

相关文章:

c++ - 如何使用 boost::property_tree 解析带根数组的 JSON

c++ - boost::lexical_cast<std::string>(Int_Type) 可以抛出吗?

java - 为 jar 可执行文件创建 Makefile

powershell - Visual Studio 代码 cmd 错误 : Cannot be loaded because running scripts is disabled on this system

c++ - boost::program_options:如何在没有 "--"或 "-"的情况下指定命令

c++ - 无法使用 boost::iostreams::file 打开文件

c++ - boost::lockfree::stack 可以安全地接受字符串指针吗?

command-line - 如何在没有 "flags"包的情况下在 Go 中获取命令行参数?

c++ - boost::program_options 可以使用 "-"以外的定界符吗?

c++ - boost program_options : help vs. 有意义的选项