Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using boost::program_options with own template class possible?

I'm currently start using boost::program_options for parsing command line options as well as configuration files.

Is it possible to use own template classes as option arguments? That means, something like

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

namespace po = boost::program_options;

template <typename T>
class MyClass
{
private:
    T*   m_data;
    size_t m_size;
public:
    MyClass( size_t size) : m_size(size) { m_data = new T[size]; }
    ~MyClass() { delete[] m_data; }
    T get( size_t i ) { return m_data[i]; }
    void set( size_t i, T value ) { m_data[i] = value; }
};

int main (int argc, const char * argv[])
{    
    po::options_description generic("General options");
    generic.add_options() ("myclass", po::value< MyClass<int>(2) >(), 
                           "Read MyClass");
    return 0;
}

Trying to compile this I get an Semantic Issue (No matching function for call to 'value'). I guess I need to provide some casting to an generalized type but I have no real idea.

Can anybody help? Thanks

Aeon512

like image 596
Aeon512 Avatar asked Jul 15 '26 08:07

Aeon512


2 Answers

I would write it like this:

MyClass<int> mine(2);
generic.add_options() ("myclass", po::value(&mine), "Read MyClass");

Then all that needs to be done is to define an input stream operator like this:

std::istream& operator >>(std::istream& source, MyClass& target);

Then Boost Program Options will invoke this stream operator when the myclass option is used, and your object will be automatically populated according to that operator's implementation, rather than having to later call one of the Program Options functions to extract the value.

If you don't prefer the above syntax, something like should work too:

generic.add_options() ("myclass", po::value<MyClass<int> >()->default_value(MyClass<int>(2)), "Read MyClass");

This way you would be creating the instance of your class directly with your desired constructor argument outside of the template part where runtime behavior isn't allowed. I do not prefer this way because it's verbose and you end up needing to call more functions later to convert the value.

like image 200
John Zwinck Avatar answered Jul 17 '26 15:07

John Zwinck


I wouldn't know if boost::program_options allows the use-case you are trying, but the error you are getting is because your are trying to pass an object as a template type to po::value<>. If the size is known at compile-time, you could have the size be passed in as a template parameter.

template< typename T, size_t size >
class MyClass {
  T m_data[size];
public:
  // ...
};

And then use it like so:

po::value< MyClass<int, 2> >()

You should also look into using Boost.Array instead that I guess fulfills what you are trying to implement.

like image 30
Oskar N. Avatar answered Jul 17 '26 17:07

Oskar N.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!