Возможно ли использовать boost :: program_options с собственным классом шаблона? - PullRequest
3 голосов
/ 21 апреля 2011

В настоящее время я начинаю использовать boost :: program_options для анализа параметров командной строки, а также файлов конфигурации.

Можно ли использовать собственные классы шаблонов в качестве аргументов параметров?Это означает, что-то вроде

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

. Пытаясь скомпилировать это, я получаю семантическую проблему (нет соответствующей функции для вызова 'value').Я предполагаю, что мне нужно предоставить некоторую приведение к обобщенному типу, но я понятия не имею.

Кто-нибудь может помочь?Спасибо

Aeon512

Ответы [ 2 ]

2 голосов
/ 21 апреля 2011

Я бы не знал, позволяет ли boost :: program_options использовать вариант использования, который вы пытаетесь использовать, но ошибка, которую вы получаете, заключается в том, что вы пытаетесь передать объект как тип шаблона в po :: value <>. Если размер известен во время компиляции, вы можете передать размер в качестве параметра шаблона.

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

А затем используйте его так:

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

Вам также следует использовать Boost.Array , который, как я полагаю, выполняет то, что вы пытаетесь реализовать.

1 голос
/ 21 апреля 2011

Я бы написал так:

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

Тогда все, что нужно сделать, это определить оператор входного потока следующим образом:

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

Тогда Boost Program Options вызовет этот оператор потока, когда используется опция myclass, и ваш объект будет автоматически заполнен в соответствии с реализацией этого оператора, вместо того, чтобы позже вызывать одну из функций Program Options, чтобы извлечь значение .

Если вы не предпочитаете приведенный выше синтаксис, тоже должно работать что-то вроде:

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

Таким образом, вы будете создавать экземпляр вашего класса напрямую с желаемым аргументом конструктора вне части шаблона, где поведение во время выполнения не разрешено. Я не предпочитаю этот способ, потому что он многословный, и вам в конечном итоге придется вызывать больше функций позже для преобразования значения.

...