Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Зафиксировать enum. 
:(
    Опции темы
semibug
Дата 10.10.2011, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



В заголовочном файле описаны коды операций в виде enum:

Код

class Foo
{
public:

  struct Codes
  {
    enum CodeEnum
    {
      codeA = 0,
      codeB,
      codeC,
      codeD,

      codeCount
    };
  };
};


codeCount используется для получения кол-ва возможных кодов.
Как указать (ну кроме как явным комментарием конечно  smile ) на то, чтобы сопровождающие не указывали явно иных значений для перечислений, дабы не сбить значение codeCount?

PM   Вверх
bsa
Дата 10.10.2011, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



semibug, явным комментарием...
PM   Вверх
boostcoder
Дата 11.10.2011, 04:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



semibug, в с++11 добавили такую замечательную вещь, как enum class.
пример:
Код

enum class myenum {
   e1
};

enum myenum2 {
   e2
};

void func(const myenum) {
}

int main() {
   func(myenum::e1); // Ок
   func(3); // error: cannot convert 'int' to 'myenum' for argument '1' to 'void func(myenum)'
   func(e2); // error: cannot convert 'myenum2' to 'myenum' for argument '1' to 'void func(myenum)'
   func(myenum2::e2); // error: cannot convert 'myenum2' to 'myenum' for argument '1' to 'void func(myenum)'
}

http://liveworkspace.org/code/73e392e9d19c...4b7efced184549a

спасибо ;)
PM WWW   Вверх
semibug
Дата 11.10.2011, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



boostcoder, интересно, как они планируют сериализировать значения таких enum class -ов.
В моем случае как раз приходится гнать в поток по сети команды, обозначенные через enum. Сейчас пришел к тому, чтобы представить их явно в виде static const unsigned char CodeA = 0x00;, хотя и спорно, т.к. легко можно вбить неверное значение при определении нового кода (например уже задействованное). С другой стороны отпадает необходимость приведения к unsigned char.
Была громоздкая идея с "фабрикой" констант, либо с кодогенерацией по XML-описанию, но коллеги по цеху замЫкали.


PM   Вверх
boostcoder
Дата 11.10.2011, 08:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



нифига не понял smile 
PM WWW   Вверх
mes
Дата 11.10.2011, 08:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(semibug @  11.10.2011,  06:41 Найти цитируемый пост)
Была громоздкая идея с "фабрикой" констант, либо с кодогенерацией по XML-описанию, но коллеги по цеху замЫкали.

вот еще одна :
Код

#include <iostream>
#include <set>
#include <vector>


struct msg { 
   unsigned code; 
   std::vector<std::string> args; 
}; 

struct command_type
{
    unsigned code;
    
    command_type (unsigned code) : code(code)
    {
       if (_register.count(code)) throw 1;       
       
       _register.insert(code);
    }
    ~command_type ()
    {
       _register.erase(code);
    }
    msg operator () (std::vector<std::string> && args)
    {
       return {code, args};
    }
    
    static std::set<unsigned> _register;    
};


std::set<unsigned>  command_type::_register 
           = { 0, 10, 100 };  //  зарегистрированные комманды, которые нельзя использовать.. 

std::ostream& operator <<  (std::ostream& o, msg const& m) 
{
       o << m.code << " ( ";
    
       for (auto i: m.args)
          o << "'" << i << "' ";      
       
       o << ") " << std::endl;
    
       return o;
}

command_type 
  cmdA = { 1 }
, cmdB = { 5 }
, cmdC = { 20 }
//, cmdD = { 20 }  // exception : double defined
//, cmdE = { 100 } // exeption  : reserved
;


int main ()
{

   std::cout
   << cmdA ({"hallo" , "world", "!"})
   << cmdB ({"bye!"});
   
   
}

Цитата

1 ( 'hallo' 'world' '!' ) 
5 ( 'bye!' ) 

http://liveworkspace.org/code/8476d100e441...a3e6d79e21a8ae0

немного с C++0x, чтоб было меньше писанины.. 


Это сообщение отредактировал(а) mes - 11.10.2011, 08:59


--------------------
PM MAIL WWW   Вверх
newbee
Дата 11.10.2011, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



boostcoder, хрень какая-то, с обычным енумом точно так же не даст передать в foo(myenum) ничего кроме описанных в myenum имен. И собственно ТС не этого хочет.


--------------------
You're face to face
With man who sold the world
PM   Вверх
mes
Дата 11.10.2011, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(newbee @  11.10.2011,  08:03 Найти цитируемый пост)
 какая-то

если речь о enum class'e то на самом деле у него  есть масса замечательных качеств, просто в примере они не были отражены.. 
а если о том что он все равно не решает задачи тс, то согласен smile 


Это сообщение отредактировал(а) mes - 11.10.2011, 11:39


--------------------
PM MAIL WWW   Вверх
mes
Дата 11.10.2011, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



добавил имя для типа комманды и возможности динамического получения объекта команды как по имени так и по коду.. 

http://liveworkspace.org/code/6ba6692806dd...41114cfef62b599

Это сообщение отредактировал(а) mes - 11.10.2011, 12:19


--------------------
PM MAIL WWW   Вверх
mes
Дата 11.10.2011, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



используем аргументы любого типа при вызове и автоматическую конвертацию :
http://liveworkspace.org/code/34e1c13ef170...97d6a84cf297e5f

Добавлено @ 16:02
хм.. где то я уже такое на этом форуме писалл .. 

Это сообщение отредактировал(а) mes - 12.10.2011, 02:33


--------------------
PM MAIL WWW   Вверх
mes
Дата 12.10.2011, 02:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(semibug @  11.10.2011,  06:41 Найти цитируемый пост)
можно вбить неверное значение при определении нового кода (например уже задействованное)

добавлена автоматическая енумерация кодов..
http://liveworkspace.org/code/34e1c13ef170...97d6a84cf297e5f
можно также добавить указание диапазона при определении типов комманд, для лучшего контроля..

Добавлено через 55 секунд
boostcoder,  а что gcc не умеет еще констуктор из конструктора вызывать ?



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 12.10.2011, 06:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  12.10.2011,  02:31 Найти цитируемый пост)
а что gcc не умеет еще констуктор из конструктора вызывать ?

нет. даже в 4.7.0 не реализовано.
PM WWW   Вверх
semibug
Дата 12.10.2011, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



Альтернатива с помощью кодогенерации по XML описанию:

Код

<enum name="foo">
    <value>CodeA</value>
    <value>CodeB</value>
    <value>CodeC</value>
    <value>CodeB = 3</value>
</enum>


+

Код

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:output method="text"/>
    <xsl:template match="/enum">
        <xsl:text>enum </xsl:text>
        <xsl:value-of select="@name"/>
        <xsl:text> {
</xsl:text>
        <xsl:for-each select="//value">
            <xsl:text>    </xsl:text>
            <xsl:value-of select="."/>
            <xsl:variable name="valueName">
                <xsl:value-of select="."/>
            </xsl:variable>
            <xsl:if test="contains($valueName, '=')"> ERROR</xsl:if>
            <xsl:text>,
</xsl:text>
        </xsl:for-each>
        <xsl:text>};
</xsl:text>
    </xsl:template>
</xsl:stylesheet>


=

Код

enum foo {
    CodeA,
    CodeB,
    CodeC,
    CodeB = 3 ERROR,
};


PM   Вверх
math64
Дата 12.10.2011, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(semibug @  12.10.2011,  08:21 Найти цитируемый пост)
Альтернатива с помощью кодогенерации по XML описанию:

Запятую после последнего значения нужно убрать
PM   Вверх
semibug
Дата 12.10.2011, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



math64, это моя дурная привычка - оставлять запятую после последнего enum-а, чтобы дописывать было проще (так или иначе компилируется вроде).
А по хорошему тогда так:

Код

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:output method="text"/>
    <xsl:template match="/enum">
        <xsl:text>enum </xsl:text>
        <xsl:value-of select="@name"/>
        <xsl:text> {
</xsl:text>
        <xsl:for-each select="//value">
            <xsl:text>    </xsl:text>
            <xsl:value-of select="."/>
            <xsl:variable name="valueName">
                <xsl:value-of select="."/>
            </xsl:variable>
            <xsl:if test="contains($valueName, '=')"> ERROR</xsl:if>
            <xsl:if test="not (position()=last())">
                <xsl:text>,
</xsl:text>
            </xsl:if> 
        </xsl:for-each>
        <xsl:text>
};
</xsl:text>
    </xsl:template>
</xsl:stylesheet>


Это сообщение отредактировал(а) semibug - 12.10.2011, 08:41
PM   Вверх
semibug
Дата 12.10.2011, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



В продолжение темы, какими инструментами лучше воспользоваться для предварительного анализа кода?
К примеру поставив такую задачу выполняться перед сборкой, можно застраховаться от некоторых проблем.
В этом конкретном случае проверка должна заключаться в поиске знака "=" в пределах блока, обозначенного фигурными скобками, предваренного заданным идентификатором (именем перечисления), в указанном файле.
Сразу на ум приходят регулярные выражения.
Наверняка есть какие либо готовые системы такой статической проверки исходного кода?



PM   Вверх
mes
Дата 12.10.2011, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



semibug, я так понимаю Вы примеры не смотрели.. 
вот вам упрощенная вырезка для допиливания под нужды :

Код

struct Enum 
{
   static unsigned current;
   static unsigned last;
   
   unsigned value;
   
   operator unsigned () const { return value; } 
   
   Enum () : value ( current++ ) {  if (current > last) throw; } 
   
};

unsigned Enum::current  = 0;
unsigned Enum::last     = 100;

Enum a,b,c,d,e,f,g; 


int main ()
{

     for (auto i : { a,b,c,d,e,f,g } )
       std::cout << i << " ";
}

http://liveworkspace.org/code/0aa33cd6c94f...dc91a54e75a689b

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




--------------------
PM MAIL WWW   Вверх
semibug
Дата 12.10.2011, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



mes, не только смотрел, но и пробовал использовать, благодарю за помощь.
К сожалению ни вариант с фабрикой, ни с генерацией по XML не одобрил руководитель проекта, с мотивацией "излишние сущности", т.е. в нашем случае остались классические перечисления enum, с явным комментарием, как и предлагал bsa.
PM   Вверх
math64
Дата 12.10.2011, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Можно с помощью макросов - но, возможно, тоже скажут "излишние сущности", но иногда полезно
Код

#include <stdio.h>
#define ENUM \
 E(a, =10, "this is 'a'") D \
 E(b, , "this is 'b'") D \
 E(c, =10, "this is 'c'")
#define E(e,v,c) e v
#define D ,
enum Enum {
  ENUM
};
#undef E
#undef D
#define E(e,v,c) case e: return c;
#define D
const char* comment(enum Enum e) {
  switch(e) {
    ENUM
  }
}
#undef E
#undef D
#define E(e,v,c) e
#define D ,
static enum Enum enums[] = {
  ENUM
};
const int cnt = sizeof(enums)/sizeof(enums[0]);
int main() {
  int i;
  for(i = 0; i < cnt; i++)
    printf("%d: %s\n", enums[i], comment(enums[i]));
}

Сообщения компилятора:
Код

test.c: In function `comment':
test.c:17: error: duplicate case value
test.c:17: error: previously used here

(к сожалению, компилятор не выдаёт в сообщении об ощибке повторяющееся значение - строка одна и та же, поскольку используется макрос.
Вывод программы после исправления ошибки:
Код

10: this is 'a'
11: this is 'b'
12: this is 'c'

PM   Вверх
math64
Дата 19.10.2011, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Тоже самое можно сделать без #undef:
Код

#include <stdio.h>

#define NAME(e,v,c) e
#define NAME_VALUE(e,v,c) e v
#define CASE(e,v,c) case e: return c;
#define COMMA ,
#define EMPTY

#define ENUM(E,D) \
 E(a, =10, "this is 'a'") D \
 E(b, , "this is 'b'") D \
 E(c, =10, "this is 'c'")

enum Enum {
  ENUM(NAME_VALUE,COMMA)
};

const char* comment(enum Enum e) {
  switch(e) {
    ENUM(CASE,EMPTY)
  }
}

static enum Enum enums[] = {
  ENUM(NAME,COMMA)
};
const int cnt = sizeof(enums)/sizeof(enums[0]);

int main() {
  int i;
  for(i = 0; i < cnt; i++)
    printf("%d: %s\n", enums[i], comment(enums[i]));
}

PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2653 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.