Можете ли вы сделать инкремент постоянной компилятором? - PullRequest
13 голосов
/ 01 апреля 2010

звучит бессмысленно .....

Я хочу постоянную, где каждый раз, когда вы используете ее, она будет увеличиваться на 1

int x;
int y;
x = INCREMENTING_CONSTANT;
y = INCREMENTING_CONSTANT;

где х == 1; и у == 2

Обратите внимание, я не хочу, чтобы у = INCREMENTING_CONSTANT + 1 тип решения.

По сути, я хочу использовать его как уникальный идентификатор времени компиляции (обычно он не будет использоваться в коде, подобном примеру, но внутри другого макроса)

Ответы [ 9 ]

8 голосов
/ 01 апреля 2010

Это не стандартно, но некоторые компиляторы поддерживают макрос __COUNTER__ . См. Кто-нибудь когда-либо использовал макрос препроцессора __COUNTER__?

7 голосов
/ 01 апреля 2010

Если вам просто нужен уникальный идентификатор ish , можете ли вы использовать символ препроцессора __LINE__? Это не то, что вы просите, но это может сработать для ваших целей.

7 голосов
/ 01 апреля 2010

Вы можете собрать что-нибудь вместе, используя Boost.Preprocessor (Работает с C) и BOOST_PP_COUNTER

Пример, приведенный на странице документы :

#include <boost/preprocessor/slot/counter.hpp>   
BOOST_PP_COUNTER // 0

#include BOOST_PP_UPDATE_COUNTER()   
BOOST_PP_COUNTER // 1

#include BOOST_PP_UPDATE_COUNTER()  
BOOST_PP_COUNTER // 2

#include BOOST_PP_UPDATE_COUNTER()
BOOST_PP_COUNTER // 3

Переведено на то, что вы хотите

#include <boost/preprocessor/slot/counter.hpp> 

int x = BOOST_PP_COUNTER; // 0

#include BOOST_PP_UPDATE_COUNTER()   
int y = BOOST_PP_COUNTER;// 1

#include BOOST_PP_UPDATE_COUNTER()  
int z = BOOST_PP_COUNTER; // 2

Вы также можете использовать слоты (немного более гибкие за счет большего количества кода, чем приведенное выше решение):

#include <boost/preprocessor/slot/slot.hpp>

#define BOOST_PP_VALUE 0 //ensure 0 to start
#include BOOST_PP_ASSIGN_SLOT(1) 
int a = BOOST_PP_SLOT(1); //0

#define BOOST_PP_VALUE 1 + BOOST_PP_SLOT(1)
#include BOOST_PP_ASSIGN_SLOT(1) 
int b = BOOST_PP_SLOT(1); //1
2 голосов
/ 12 декабря 2012

В моем случае я хотел иметь системный уникальный ключ для каждой подсистемы, но выбор подсистем зависел бы от человека, использующего систему. Это должны быть 8-битные значения, потому что они предназначены для встраиваемых систем.

Вот что я придумал только сейчас:

#define LAST_KEY -1

// SUB1_KEY definition
enum {
  SUB1_KEY_ORIGIN = LAST_KEY,
  SUB1_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB1_KEY

// SUB2_KEY definition
enum {
  SUB2_KEY_ORIGIN = LAST_KEY,
  SUB2_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB2_KEY

// SUB3_KEY definition
enum {
  SUB3_KEY_ORIGIN = LAST_KEY,
  SUB3_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB3_KEY

// ....

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

1 голос
/ 01 апреля 2010

Я часто мечтал о переменных времени компиляции. Однако проще всего было бы определить константы для каждого из них по отдельности.

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

Вы также можете попробовать использовать xmacro. Создайте новый файл, назовем его xmacro.h

INCREMENTING_CONSTANT;
#define INCREMENTING_CONSTANT INCREMENTING_CONSTANT + 1

Затем в стандартном заголовке

#define INCREMENTING_CONSTANT 0
#define USE_INCREMENTING_CONSTANT #include "xmacro.h"

const int x = USE_INCREMENTING_CONSTANT

Я не проверял это, но xmacros обладает удивительной мощью, которую обычные макросы не могут использовать, например defs / undefs, и моя интуиция говорит, что это должно работать. Препроцессор мощный, но довольно тупой, поэтому может потерпеть неудачу.

0 голосов
/ 01 апреля 2010

Вот ужасный способ реализовать это.

static int _counter=0;
#define INCREMENTING_CONSTANT (_counter++)
0 голосов
/ 01 апреля 2010

Вы хотите, чтобы x и y сами были константами? Если так, то проще всего и проще всего использовать анонимное перечисление:

enum {
    x = 1,
    y
    /* Add new ones here. */
};

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

enum {
    button1_id = FIRST_USER_ID,
    button2_id,
    combo_id,
    ...
}

Некоторые инфраструктуры GUI предоставляют функцию GetUserId (), которая будет генерировать новую (с использованием внутренней статической переменной); но я думаю, что это происходит во время выполнения. Также немного утомительно видеть так много звонков подряд.

button1_id = GetUserId();
button2_id = GetUserId();
combo_id = GetUserId();
...
0 голосов
/ 01 апреля 2010

«Константа приращения» - оксюморон. Вы не можете сделать это во время компиляции.

0 голосов
/ 01 апреля 2010

Ну, тогда это не постоянно, не так ли? ;)

Вы можете сделать это с помощью функции:

int id() {
  static int i = 0;
  return ++i;
}

x = id();
y = id();

Как показано, это не потокобезопасно. Для этого вам необходимо защитить его мьютексом или использовать атомарный инкрементатор, специфичный для компилятора / платформы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...