如何解析与升压:: program_options逗号分隔值? [英] How to parse comma separated values with boost::program_options?

查看:214
本文介绍了如何解析与升压:: program_options逗号分隔值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要解析如 - 值= STR1,STR2,STR3 使用的boost :: program_options CMD。我发现<一个href=\"http://stackoverflow.com/questions/3065109/can-boost-program-options-separate-comma-separated-argument-values\">exactly同样的问题,但它不工作了(有提升1.55和1.56)。

我试图定义自己的等级和映射器,但没有运气:

 命名空间PO =提振:: program_options;desc.add_options()
        (mattr的,PO :​​:值&LT; LLI :: CommaSeparatedVector&GT;(安培; MAttrs),目标特定属性(-mattr =详情帮助));命名空间LLI {
  类CommaSeparatedVector
  {
      上市:
        //逗号分隔值列表
        的std ::矢量&lt;标准::字符串&GT;值;
  };
}无效记号化(常量标准::字符串&放大器; STR,性病::矢量&lt;标准::字符串&GT;&安培;令牌,常量标准::字符串&安培;分隔符=)
{
  //在开始跳过分隔符。
  标准::字符串:: size_type的lastPos = str.find_first_not_of(分隔符,0);  //找到第一个非分隔符。
  标准::字符串:: size_type的POS = str.find_first_of(分隔符,lastPos);  而(标准::字符串::非营利组织!= POS ||标准::字符串::非营利组织!= lastPos){
    //发现一个道理,把它添加到载体。
    tokens.push_back(str.substr(lastPos,POS - lastPos));    //跳过分隔符。
    lastPos = str.find_first_not_of(分隔符,POS)    //查找下一个非分隔符。
    POS = str.find_first_of(分隔符,lastPos);
  }
}//映射器LLI :: CommaSeparatedVector
的std :: istream的&安培;运营商的GT;&GT;(的std :: istream的&安培;中,LLI :: CommaSeparatedVector&安培;价值)
{
    性病::字符串标记;
    在&GT;&GT;令牌;    记号化(令牌,value.values​​);    返回;
}

错误消息:

 在文件从/softdev/boost-1.56/include/boost/program_options.hpp:15包括:
在文件从/softdev/boost-1.56/include/boost/program_options/options_description.hpp:13包括:
在文件从/softdev/boost-1.56/include/boost/program_options/value_semantic.hpp:14包括:
/softdev/boost-1.56/include/boost/lexical_cast.hpp:379:13:错误:未定义模板隐式实例
      提振:: STATIC_ASSERTION_FAILURE&LT;假&gt;'
            BOOST_STATIC_ASSERT_MSG((result_t ::值||提振:: has_​​right_shift&LT;的std :: basic_istream&LT; wchar_t的&gt;中T&GT; ::值)
            ^
/softdev/boost-1.56/include/boost/static_assert.hpp:36:48:注意:从宏观'BOOST_STATIC_ASSERT_MSG'扩大
#定义BOOST_STATIC_ASSERT_MSG(B,消息)BOOST_STATIC_ASSERT(B)
                                               ^
/softdev/boost-1.56/include/boost/static_assert.hpp:169:13:注意:从宏观'BOOST_STATIC_ASSERT'扩大
            的sizeof(::的boost :: STATIC_ASSERTION_FAILURE&LT; BOOST_STATIC_ASSERT_BOOL_CAST(__VA_ARGS__)GT;)&GT; \\
            ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:406:44:注意:在模板类的实例化
      'boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<lli::CommaSeparatedVector> &GT;'
      这里要求
            typedef的BOOST_DEDUCED_TYPENAME deduce_target_char_impl&LT; stage1_type&GT; ::类型stage2_type;
                                           ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:564:59:注意:在模板类的实例化
      提振::详细:: deduce_target_char&LT; LLI :: CommaSeparatedVector&GT;'这里要求
            的typedef BOOST_DEDUCED_TYPENAME的boost ::详细:: deduce_target_char&lt;目标&GT; ::类型target_char_t;
                                                          ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2067:40:注意:在模板类的实例化
      提振::详细:: lexical_cast_stream_traits&LT;的std :: __ 1 :: basic_string的&LT;焦炭&gt;中LLI :: CommaSeparatedVector&GT;'这里要求
                BOOST_DEDUCED_TYPENAME stream_trait :: char_type,
                                       ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2289:20:注意:在模板类的实例化
      提振::详细:: lexical_converter_impl&LT; LLI :: CommaSeparatedVector,性病:: __ 1 :: basic_string的&LT;焦炭&GT; &GT;'这里要求
            返回caster_type :: try_convert(阿根廷,结果);
                   ^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2316:41:注意:在函数模板专业化实例
      提振::转换::详细:: try_lexical_convert&LT; LLI :: CommaSeparatedVector,性病:: __ 1 :: basic_string的&LT;焦炭&GT; &GT;'要求
      这里
        如果(!提振::转换::详细:: try_lexical_convert(阿根廷,结果))
                                        ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:89:21:注意:在函数实例
      模板特'的boost :: lexical_cast的&LT; LLI :: CommaSeparatedVector,性病:: __ 1 :: basic_string的&LT;焦炭&GT; &GT;'这里要求
            V =任何(lexical_cast的&LT; T&GT;(S));
                    ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:167:13:注意:在函数实例
      模板特'的boost :: program_options ::验证&LT; LLI :: CommaSeparatedVector,焦炭&GT;'这里要求
            验证(value_store,new_tokens(T *)0,0);
            ^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:182:33:注意:在成员函数的实例化
      提振:: program_options :: typed_value&LT; LLI :: CommaSeparatedVector,焦炭&GT; :: xparse这里要求
        typed_value&LT; T&GT; * R =新typed_value&LT; T&GT;(五);
                                ^
./lib_lli.cpp:480:23:注意:在函数模板专业化实例
      的boost :: program_options ::值&LT; LLI :: CommaSeparatedVector&GT;'这里要求
        (mattr的,PO :​​:值&LT; LLI :: CommaSeparatedVector&GT;(安培; MAttrs),目标特定属性(-mattr =详情帮助));
                      ^
/softdev/boost-1.56/include/boost/static_assert.hpp:87:26:注意:模板这里声明
模板&LT;布尔X'GT;结构STATIC_ASSERTION_FAILURE;
                         ^
1警告,1误差产生的。


解决方案

您将不得不作出的运营商的GT;&GT; 发现。

由于它需要在的std :: istream的&放的左手侧的操作; 不能在拥有类中声明;但作为一个免费的功能,您将需要使用的命名空间查找为了使code找到流运营商。

现在注意,流运营商正在从内部的某处空间名为的boost ::细节(来自Boost Lexicalcast库)。

它使用的参数依赖查找的选择超载。 ADL意味着与参数类型相关联的命名空间指示哪些命名空间应搜索候选运营>>overloads.¹

这意味着,查询将搜索命名空间 STD (由于的std :: istream的参数),也 LLI (因为第二个参数类型)。请注意,如果有任何说法的类型的本身使用的模板参数的类型,命名空间(S)定义的的也包括在查找。

正如你提到的,你可以解决这个问题。


  • 将不使用的命名空间。

  • 或者,您可以定义操作>>在 LLI 命名空间内过载:<大骨节病> 住在Coliru

  • 此外,声明它的类(作为朋友静电功能,仿佛在包含命名空间中声明这将被视为):<大骨节病> 住在Coliru

¹它适用于非运营商免费功能是一样的,但

I need to parse cmd like -value=str1,str2,str3 using boost::program_options. I've found exactly the same question but it's not working anymore (with boost 1.55 and 1.56).

I've tried to define my own class and mapper but no luck:

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;
}

Error message:

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.

解决方案

You will have to make the operator>> discoverable.

Because it needs to operate on a left-hand-side of std::istream& it cannot be declared in the "owning" class; But being a free function, you will need to employ namespace lookups in order for the code to find the streaming operator.

Now note that the streaming operator is being called from somewhere inside namespace boost::detail (from the Boost Lexicalcast library).

It uses argument dependent lookup to select the overload. ADL implies that the namespaces associated with the argument types indicate which namespaces should be searched for candidate operator>> overloads.¹

This means that the lookup will search namespace std (due to the std::istream argument) and also lli (due to the second argument type). Note that if any of the argument types itself uses a template argument type, the namespace(s) defining that are also included in the lookup.

As you noted, you can get around this

  • by not using a namespace.
  • Or, you can define the operator>> overload inside the lli namespace: Live On Coliru
  • Alternatively, declare it in-class (as a friend static function, which will be treated as if were declared in the containing namespace): Live On Coliru

¹ it works for non-operator free functions just the same, though

这篇关于如何解析与升压:: program_options逗号分隔值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆