3

I am trying to parse a list input from the command line.

My class is derived from vector

The compiler complains about a overloaded validate being ambiguous. I can see why, but do not know how to solve this issue.

Please help.

Below is a minimal example that generates the error. If the type of ch_list is changed to a vector, this minimal example compiles.

// g++ -std=c++11 -Wall -Wextra -pedantic test.cpp -o test -lboost_program_options -lboost_system

#include <vector>
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>

using namespace std;

class mylist : public vector<int> {
public:
    friend istream &operator>>(istream &is, mylist& l) {
        int val;
        is >> val;
        l.push_back(val);
        return is;
    }
    friend ostream& operator<<(ostream& os, const mylist& l) {
        return os << l[0];
    }
};

int main (int argc, char* argv[])
{
    //vector<int> ch_list; // This works
    mylist ch_list; // This doesn't

    namespace po = boost::program_options;
    po::options_description desc("Allowed options");
    desc.add_options()
        ("ch", po::value<decltype(ch_list)>(&ch_list), "Set channel numbers")
    ;

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch (po::error& e) {
        cerr << "ERROR: " << e.what() << "\n";
        return EXIT_FAILURE;
    }
    if (!ch_list.empty())
        cout << ch_list[0] << "\n";

    return EXIT_SUCCESS;
}

I get these errors

/usr/include/boost/program_options/detail/value_semantic.hpp: In instantiation of ‘void boost::program_options::typed_value<T, charT>::xparse(boost::any&, const std::vector<std::basic_string<charT> >&) const [with T = mylist; charT = char]’:
test.cpp:47:5:   required from here
/usr/include/boost/program_options/detail/value_semantic.hpp:169:13: error: call of overloaded ‘validate(boost::any&, const std::vector<std::basic_string<char> >&, mylist*, int)’ is ambiguous
/usr/include/boost/program_options/detail/value_semantic.hpp:169:13: note: candidates are:
/usr/include/boost/program_options/detail/value_semantic.hpp:81:10: note: void boost::program_options::validate(boost::any&, const std::vector<std::basic_string<charT> >&, T*, long int) [with T = mylist; charT = char]
/usr/include/boost/program_options/detail/value_semantic.hpp:129:10: note: void boost::program_options::validate(boost::any&, const std::vector<std::basic_string<charT> >&, std::vector<_RealType>*, int) [with T = int; charT = char]

1 Answers1

0

You can use custom validator. Your code would be:

#include <vector>
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>

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

class mylist : public vector<int> {
public:
};

void validate(boost::any& v,
  const vector<string>& values,
  mylist*, int) {
  mylist dvalues;
  for(vector<string>::const_iterator it = values.begin();
    it != values.end();
    ++it) {
    stringstream ss(*it);
    copy(istream_iterator<int>(ss), istream_iterator<int>(),
      back_inserter(dvalues));
    if(!ss.eof()) {
      throw ("Invalid coordinate specification");
    }
  }
  v = mylist(dvalues);
}

int main (int argc, char* argv[])
{
    //vector<int> ch_list; // This works
    mylist ch_list; // This doesn't

    po::options_description desc("Allowed options");
    desc.add_options()
        ("ch", po::value< mylist  >(&ch_list)->multitoken(), "Set channel numbers")
    ;

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch (po::error& e) {
        cerr << "ERROR: " << e.what() << "\n";
        return EXIT_FAILURE;
    }

    for (auto cc : ch_list)
      cout << cc << endl;

    return EXIT_SUCCESS;
}

Reference: boost::program_options config file option with multiple tokens

Community
  • 1
  • 1
montefuscolo
  • 259
  • 2
  • 13