Как сказал Нил, я никогда не сталкивался с этой проблемой сам. Однако я столкнулся с проблемой кодовых наборов (т.е. сопоставление строки с перечислением и обратно).
Моя первая реакция эпидермальная: СУХАЯ.
Как вы заметили, поддержка двух перечислений и перевод требуют времени, поэтому лучше провести рефакторинг и использовать только один.
Моей второй реакцией было бы попытаться удалить перечисление. Я не люблю перечисления. Возможно, я оценю их в грядущем C++0x, но в нынешнем виде они доставляют больше хлопот, чем того стоят, на мой взгляд. Я предпочитаю смарт-объекты с категориями и т. д.
Но тогда сама проблема забавна, я думаю. Так что, если вам нравится разбираться с этой запутанной ситуацией, я могу попытаться облегчить ваше бремя.
Шаблоны здесь мало что могут сделать. Я использовал их для проверки диапазона в перечислениях и для преобразования строк (туда и обратно) и итераций, но это все, что они могут сделать. Однако, как вы подозревали, это возможно с помощью некоторого «тонкого» применения Boost.Preprocessor.
Что вы хотите написать:
DEFINE_CORRESPONDING_ENUMS(Server, Client,
((Server1, 1, Client1, 6))
((Server2, 2, Client2, 3))
((Common1, 4, Common1, 4))
((Common2, 5, Common2, 5))
((Server3, 7, Client3, 1))
);
И мы хотели бы, чтобы он сгенерировал:
struct Server
{
enum type { Server1 = 1, Server2 = 2, Common1 = 4, Common2 = 5, Server3 = 7 };
};
struct Client
{
enum type { Client1 = 6, Client2 = 3, Common1 = 4, Common2 = 5, Client3 = 1 };
};
Server::type ServerFromClient(Client::type c)
{
switch(c)
{
case Client1: return Server1;
//...
default: abort();
}
}
Client::type ClientFromServer(Server::type s)
{
//...
}
Хорошая новость в том, что это возможно. Я мог бы даже это сделать, хотя, вероятно, я позволю вам немного поработать над этим;)
Вот некоторые пояснения:
- Третий элемент макроса — это последовательность. Последовательность имеет неограниченный размер.
- Каждый элемент последовательности является четверкой. Вам нужно заранее знать его размер, поэтому повторение для
Common
. Если бы вы вместо этого использовали последовательность, вы могли бы иметь дело с переменным количеством элементов (например, чтобы избежать повторения общего...), но это значительно усложнило бы ситуацию.
- Вам нужно посмотреть на
BOOST_PP_SEQ_FOREACH
, здесь это будет основная операция.
- Не забудьте
BOOST_PP_CAT
для обработки конкатенации токенов.
- на
gcc
опция -E
дает вывод препроцессора, это может пригодиться...
- не забывайте комментарии и как их использовать в файле, иначе ваши коллеги будут вас ненавидеть
person
Matthieu M.
schedule
07.07.2010