2017-02-21 36 views
-1

Я пытаюсь реализовать общую структуру настроек, чтобы получить доступ ко всем настройкам моего приложения в одном месте. Каждый модуль приложения имеет свои собственные настройки class/struct. Я хочу определить член с типом каждого параметра модуля в общих настройках struct. Чтобы упростить задачу, я хочу определить макрос REGISTER, который создает новый член для каждой настройки модуля.C++ Использовать макросы для определения члена класса для одного класса

Что-то вроде этого:

struct Settings 
{  
    // I know this is not working 
    #define REGISTER_SETTINGS(settings) \ 
      settings _##settings = ##settings(); 
}; 

struct ServerSettings 
{ 
    int port = 8080; 
    string ip = "0.0.0.0"; 
}; 

REGISTER_SETTINGS(ServerSettings); 

struct WindowSettings 
{ 
    int width = 640; 
    int height = 480; 
    string title = "window"; 
}; 

REGISTER_SETTINGS(WindowSettings); 

В конце концов мои настройки структура должна выглядеть следующим образом:

struct Settings 
{ 
    ServerSettings _ServerSettings = ServerSettings(); 
    WindowSettings _WindowSettings = WindowSettings(); 
}; 

Я понятия не имею, как я должен получить макрораскрытие там.

+7

Одноязычное руководство по использованию макросов в C++: ** не **. –

+0

Вам нужно удалить точку с запятой из макроса, для одного – StoryTeller

+0

Почему вы определяете макрос внутри структуры? – user463035818

ответ

2

Вам следует избегать макросов. У меня даже не было бы смысла REGISTER_SETTINGS(settings) в моих глазах, потому что вы программист, просто напишите эти две строки в структуре настроек, и вы в порядке ... Но если вы все еще хотите, чтобы такая функция записывала его с помощью встроенного функция.

0

Вы можете сделать так:

#define REGISTER_SETTINGS(settings) \ 
     settings _##settings = settings(); 

примечание нет '##' перед settings().

Но:

  1. Как уже отмечалось в комментариях: лучше сделать не использовать макросы.
  2. Это не приведет, что вы ожидаете, например:

    struct Settings 
    { 
        ServerSettings _ServerSettings = ServerSettings(); 
        WindowSettings _WindowSettings = WindowSettings(); 
    }; 
    

    но это будет создавать объекты в месте, где под названием макроса:

    struct Settings 
    ... 
    struct ServerSettings 
    ... 
    ServerSettings _ServerSettings = ServerSettings(); 
    
    struct WindowSettings 
    ... 
    WindowSettings _WindowSettings = WindowSettings(); 
    
  3. Я предложил бы использовать некоторые creational pattern как (Аннотация) Заводской или заводской метод.

1

Как говорили другие, лучше избегать макросов.

Однако, чтобы ответить на вопрос, как спросил ....

Чтобы объявить struct тип, который имеет элементы, которые являются экземплярами struct других типов, компилятор должен уже видел декларацию тех содержащихся типов. Поэтому просто измените порядок определений.

struct ServerSettings 
{ 
    int port = 8080; 
    string ip = "0.0.0.0"; 
}; 

struct WindowSettings 
{ 
    int width = 640; 
    int height = 480; 
    string title = "window"; 
}; 

struct Settings 
{  
#define REGISTER_SETTINGS(settings) \ 
     settings _##settings = ##settings() 

    REGISTER_SETTINGS(ServerSettings); 
    REGISTER_SETTINGS(WindowSettings); 

     // etc 

#undef REGISTER_SETTINGS 
}; 

Обратите внимание на #undef предотвращает существо макро, используемый вне определения struct Settings.

Однако есть одна ключевая проблема. Это создает идентификаторы, начинающиеся с символа подчеркивания, за которым следует буква верхнего регистра. Такие идентификаторы зарезервированы стандартом C++, и их использование заставляет ваш код иметь неопределенное поведение.Один из способов избежать этого - изменить макрос на

#define REGISTER_SETTINGS(settings) \ 
    settings a_##settings = ##settings() 

, который предотвращает создание зарезервированных идентификаторов.

Во-вторых, заявление

Type name = Type(); 

в основном по-умолчанию, инициализирует name, поэтому функционально эквивалентна

Type name; 

Таким образом, вы можете еще больше упростить макрос

#define REGISTER_SETTINGS(settings) \ 
    settings a_##settings 

В I сказал в начале, однако, лучше избегать макросов целиком у. Макросы просто скрывают факт этого;

// definitions of ServerSettings and WindowSettings here 

struct Settings 
{  
    ServerSettings a_ServerSettings;  
    WindowSettings a_WindowSettings; 
}; 

, который намного легче читать, что запутывание макросов, которые вы пытаетесь использовать. Очевидно, вы можете использовать любое соглашение об именах для членов Settings, которые вам нравятся.

 Смежные вопросы

  • Нет связанных вопросов^_^