Я работаю над подсистемой парсера / генератора сообщений. Я создаю автогенератор, который использует базу данных, которая содержит всю информацию об этом протоколе, включая списки enum, для генерации кода. Одна вещь, с которой я столкнулся, - это необходимость иерархических перечислений.
обновлен
(Я пытался упростить ситуацию, не описывая проблему full , но приведенные ниже комментарии дают понять, что я допустил ошибку, упрощая слишком много.)
Используемая база данных будет хранить вещи в виде упрощенных строк (решение клиента), но протокол говорит только о «байтовых триплетах» (или иерархическом перечислении). Полная проблема может быть описана так:
Учитывая набор уникальных строк, каждая из которых соответствует уникальному триплету, 1) найти триплет для любой заданной строки, и 2) найти строку для любого заданного триплета. Убедитесь, что учтены перечисления «Undefined» и «No Statement» (с которыми не связаны строки). [Как заметил один из авторов, да, это безумно.]
(Предостережение: я занимался C ++ уже более десяти лет, но я занимался Java в прошлом году - мой C ++, вероятно, "поврежден".)
Итак, воспользуемся общеизвестным надуманным примером, приведенным:
// There is only one category
// POP= "P", COUNTRY= "K", CLASSICAL= "C"
enum Category {POP, COUNTRY, CLASSICAL};
// There is one Type enum for each Category.
// ROCK= "R", BIG_BAND = "B", COUNTRY_POP= "C"
enum PopType {ROCK, BIG_BAND, COUNTRY_POP};
enum CountryType {CLASSICAL_COUNTRY, MODERN_COUNTRY, BLUEGRASS, COUNTRY_AND_WESTERN};
// ...
// There is one Subtype for each Type
// EIGHTIES= "E", HEAVY_METAL= "H", SOFT_ROCK= "S"
enum RockSubType { EIGHTIES, HEAVY_METAL, SOFT_ROCK};
// ...
Когда я получаю 0, 0, 0 (поп, рок, восьмидесятые), мне нужно перевести это на «PRE». И наоборот, если я вижу «ПК» в базе данных, его нужно отправить по проводам как 0, 2 (Pop, Country, NULL).
Я явно игнорирую «Undefined» и «No Statement» на этом этапе. Генерация триплета из строки кажется простой (используйте неупорядоченную карту, строка для тройки). Генерация строки из триплета (которая может содержать NULL в последней записи) ... не так много. Большинство известных мне трюков enum не сработает: например, типы повторяют значения - каждое перечисление типов начинается с нуля, поэтому я не могу индексировать массив, основанный на значении Enum для захвата строки.
Что меня заинтересовало, так это отношения. На первый взгляд, это довольно прямолинейные отношения «есть», но это не работает, потому что этот случай двунаправленный. Листовая -> корневая навигация очень прямолинейна и подходит для иерархии классов; к сожалению, идти другим путем не так уж и просто.
Я не могу это «свернуть вручную» - мне нужно сгенерировать код - так что, вероятно, устраняются любые решения на основе XML. Это также должно быть "достаточно быстро". «Решение Java» включает использование защищенных статических переменных, инициализированных при построении, и абстрактных базовых классов; однако я не верю, что это будет работать в C ++ (порядок инициализации и т. д.). Плюс, эстетически, я чувствую, что это должно быть ... больше "const". Другой код, который я видел для решения этой проблемы, использует объединения, явно перечисляя все типы перечислений в объединении.
Единственное, что я могу придумать, это использовать специализацию шаблонов и явную специализацию, но я в растерянности. Я сделал поиск в Интернете по этому вопросу, но я не нашел ничего, что могло бы сказать мне, будет ли это вообще работать. Тем не менее, если это можно сделать с помощью объединения, не может ли это быть сделано с помощью специализации шаблонов?
Можно ли сделать что-то подобное, используя шаблоны, специализацию, явную специализацию? Есть ли другое, более очевидное, решение (то есть шаблон проектирования, который я забыл), которое мне не хватает?
О, прежде чем я забуду - решение должно быть портативным. В частности, он должен работать в Windows (Visual Studio 2010) и Redhat Enterprise 6 / Centos 6 (GCC 4.4.4 IIRC).
И, чтобы я не забыл, этот протокол огромен . Теоретический максимум на это составляет около 133 000 записей; как только я добавлю «Undefined» и «No Statement», у меня, вероятно, будет столько записей.
Спасибо.