2015-01-08 2 views
1

Я наблюдаю любопытное поведение функции boost::program_options::value с классами STL. Мне часто приходится предоставлять аргументы программам в парах, например. имена файлов с короткими метками, но функция boost::program_options::value, похоже, не работает с std::pair, в то время как она работает с любым классом, который я сам определяю. Рассмотрим следующий код:Boost program options Пара значение

#include <string> 
#include <utility> 

#include <boost/program_options.hpp> 

using namespace std; 
namespace po = boost::program_options; 

class sspair: public pair<string,string> { }; 

typedef pair<string,string> mypair; 
// typedef sspair mypair; 

istream& operator>>(istream& in, mypair& ss) { 
    string s; 
    in >> s; 
    const size_t sep = s.find(':'); 
    if (sep==string::npos) { 
    ss.first = string(); 
    ss.second = s; 
    } else { 
    ss.first = s.substr(0,sep); 
    ss.second = s.substr(sep+1); 
    } 
    return in; 
} 

int main(int argc, char **argv) 
{ 
    mypair a; 

    try { 
    po::options_description all_opt("Options"); 
    all_opt.add_options() 
     ("arg,a", po::value<mypair>(&a),"colon separated pair") 
    ; 

    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, all_opt), vm); 
    po::notify(vm); 
    } catch(exception& e) { 
    cerr << e.what() << endl; 
    exit(1); 
    } 

    cout << "a = (" << a.first << ", " << a.second << ")" << endl; 

    return 0; 
} 

С typedef sspair mypair я получаю ожидаемое поведение.

$ ./test 
a = (,) 
$ ./test -a b:c 
a = (b, c) 
$ ./test -a bc 
a = (, bc) 

но с typedef pair<string,string> mypair я получаю следующие ошибки компиляции:

In file included from /usr/include/boost/any.hpp:27:0, 
       from /usr/include/boost/program_options/value_semantic.hpp:12, 
       from /usr/include/boost/program_options/options_description.hpp:13, 
       from /usr/include/boost/program_options.hpp:15, 
       from test.cc:4: 
/usr/include/boost/lexical_cast.hpp: In instantiation of ‘struct boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<std::pair<std::basic_string<char>, std::basic_string<char> > > >’: 
/usr/include/boost/lexical_cast.hpp:415:89: required from ‘struct boost::detail::deduce_target_char<std::pair<std::basic_string<char>, std::basic_string<char> > >’ 
/usr/include/boost/lexical_cast.hpp:674:92: required from ‘struct boost::detail::lexical_cast_stream_traits<std::basic_string<char>, std::pair<std::basic_string<char>, std::basic_string<char> > >’ 
/usr/include/boost/lexical_cast.hpp:2363:19: required from ‘static Target boost::detail::lexical_cast_do_cast<Target, Source>::lexical_cast_impl(const Source&) [with Target = std::pair<std::basic_string<char>, std::basic_string<char> >; Source = std::basic_string<char>]’ 
/usr/include/boost/lexical_cast.hpp:2543:50: required from ‘Target boost::lexical_cast(const Source&) [with Target = std::pair<std::basic_string<char>, std::basic_string<char> >; Source = std::basic_string<char>]’ 
/usr/include/boost/program_options/detail/value_semantic.hpp:89:38: required from ‘void boost::program_options::validate(boost::any&, const std::vector<std::basic_string<charT> >&, T*, long int) [with T = std::pair<std::basic_string<char>, std::basic_string<char> >; charT = char]’ 
/usr/include/boost/program_options/detail/value_semantic.hpp:170:55: required from ‘void boost::program_options::typed_value<T, charT>::xparse(boost::any&, const std::vector<std::basic_string<charT> >&) const [with T = std::pair<std::basic_string<char>, std::basic_string<char> >; charT = char]’ 
test.cc:49:1: required from here 
/usr/include/boost/lexical_cast.hpp:388:13: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>’ 
      BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value), 
      ^
make: *** [test] Error 1 

Я обнаружил, что подобное поведение имеет место, если я пытаюсь использовать другие СТЛ контейнеры, как std::array или std::tuple.

Кто-нибудь знает, в чем проблема?

EDIT:

Хорошо, я только что узнал, что вызывает этот вопрос, после того, как я прочитал эту post. По-видимому, оператор потока просматривается только в пространстве имен, в котором был определен класс, являющийся аргументом шаблона функции po :: value. Так, с редактированием

namespace std { 
    istream& operator>>(istream& in, mypair& ss) { ... } 
} 

pair<string,string> класс работает напрямую.

Теперь существует ли недостаток в определении оператора в пространстве имен std? Я слышал, что это не стандарт, как таковой.

ответ

1

Извините, у вас есть только быстрый ответ.

Если вы хотите использовать std::pair<std::string, std:string> в вашей паре, вам нужно будет написать operator>>(...) для него, и этот оператор также должен быть в namespace std, так что ADL работы.

 Смежные вопросы

  • Нет связанных вопросов^_^