2012-05-14 5 views
0

В основном это следующий код, который не может передать компилятор (г ++)с использованием повышение :: program_options, как статические члены класса

#include <boost/program_options.hpp> 
#include <iostream> 
using std::cout; 
using std::endl; 
namespace po = boost::program_options; 

class static_class { 
public: 
    static po::options_description cmd_opt; // here is the definition 
}; 

po::options_description static_class::cmd_opt("dummy"); 
// the line below cannot pass the compiler !!! 
static_class::cmd_opt.add_options() 
("help", "show usage info.") 
; 

main() { 
    cout << static_class::cmd_opt << endl; 
} 

Сообщение об ошибке:

test.cpp:16:1: error: ‘cmd_opt’ in class ‘static_class’ does not name a type 

Любая идея?

P.S. Я пытаюсь определить разделенный options_description для каждой команды, которую мне нужно обрабатывать в среде с небольшой командной строкой. Я использую bison и flex для анализа среды командной строки. Все аргументы команды будут отправлены в этот статический класс для разбора аргументов.

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

ответ

3

Вам не разрешено иметь автономные операторы в глобальном или пространстве имен.

Вы можете обойти проблему, используя возвращаемое значение расширенного выражения add_options, чтобы объявить и инициализировать фиктивную переменную, как показано ниже.

po::options_description static_class::cmd_opt("dummy"); 

auto const dummy = cmd_opt.add_options() 
    ("help", "show usage info.") 
    ; 

Если ваша версия C++ не поддерживает auto подобное, то вы можете использовать полное имя типа, в po::options_description_easy_init, вместо этого.

+0

Это выглядит немного странно, но просто фантастично! Я попробую позже. –

+0

Я думаю, что добавление статики в фиктивную переменную, что делает ее видимой только в локальном файле еще лучше.При этом одна и та же фиктивная переменная может использоваться в нескольких файлах cpp. –

3

Звонок .add_options() является вызовом функции , а не декларацией. Вы пытаетесь запустить код вне функции. Попробуйте это:

// untested 
void PopulateOptions() { 
    static_class::cmd_opt.add_options() 
    ("help", "show usage info.") 
    ; 
} 

int main() { 
    PopulateOptions(); 
} 
+0

Вы правы по причине этой ошибки, но явное добавление вызова функции в main() - именно то, чего я пытаюсь избежать. –

+0

Если бы это было важным ограничением, было бы неплохо добавить его в ваш оригинальный пост. –

3

Судя по options_description требует инициализации двухфазный: вызовите конструктор, а затем вызвать add_options() для его заполнения. Ваш код пытается выполнить вторую фазу вне области действия и не работает, потому что вызов add_options() должен выполняться в области функций.

Один из способов исправить это, чтобы создать фабричную функцию, которая инициализирует и заполняет объект options_description и возвращает его. Это возвращение объект может быть использован для инициализации статического экземпляра static_class::cmd_opt, например:

// in .cc 

namespace { 

po::options_description make_options_description() { 
    po::options_description opt("dummy"); 
    opt.add_options() // ... populate ... 
    return opt; 
} 

} 

po::options_description static_class::cmd_opt = make_options_description(); 

Другое вариантов вместо того, чтобы подвергать po::options_description статический член, выставить функцию, заполняющий po::options_description объект передается по ссылке, например:

class static_class { 
public: 
    // requires only a forward declaration of po::options_description 
    static void add_options(po::options_description&); 
}; 

// in .cc 
void static_class::add_options(po::options_description& opt) { 
    opt.add_options() // ... populate ... 
} 

А потом где-то в main()

po::options_description opt; 
static_class::add_options(opt); 
another_static_class::add_options(opt); 
yet_another_static_class::add_options(opt); 
+0

Спасибо, прямо на точку! Извините, что может быть принят только один ответ. –