Пользовательский валидатор для boost program_options не работает с GCC, работает с MSVC

Допустим, мне нужна специальная обработка целочисленных опций. Согласно документации, я должен написать свою собственную функцию проверки. Рассмотрим следующую короткую программу.

#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 он никогда не входит в функцию проверки.

Доказательство: http://coliru.stacked-crooked.com/a/fd558ebf987a4bbe

Если я попытаюсь использовать пользовательский тип вместо unsigned int, GCC все равно попытается использовать validate из program_option и в итоге получит кучу ошибок.

Что я делаю не так?

1 ответ

Решение

На предварительном догадке, рассмотреть вопрос об использовании

BOOST_STRONG_TYPEDEF(unsigned int, Unsigned);

Кажется плохой идеей настраивать поведение только для встроенных типов.


Решение: это связано с частичным упорядочением.

Если вы переместите свою перегрузку за пределы boost::program_options Пространство имён он начнет работать (так как он больше не конкурирует с базовым шаблоном).

Жить на Колиру

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

Причиной является, вероятно, 2-фазный поиск MSVC.

Другие вопросы по тегам