Я бы продолжил ваш подход «преобразовать число в строку». Однако вы поймете, что ваш предложенный алгоритм терпит неудачу, если ваш идентификатор является простым и большим, чем 52 .
Вам нужен Bijective Функция f . Это необходимо, чтобы вы могли найти обратную функцию g ('abc') = 123 для функции f (123) = 'abc' . Это означает:
[a-zA-Z0-9]
. Он содержит 62 буквы . id
таблицы MySQL). В этом примере я буду использовать 12510 (125 с базой 10). [2,1]
Для этого требуется использование целочисленного деления и по модулю. Пример псевдокода: digits = []
while num > 0
remainder = modulo(num, 62)
digits.push(remainder)
num = divide(num, 62)
digits = digits.reverse
Теперь сопоставьте индексы 2 и 1 с вашим алфавитом. Так будет выглядеть ваше сопоставление (например, с массивом): 0 → a
1 → b
...
25 → z
...
52 → 0
61 → 9
С 2 → c и 1 → b вы получите cb62 как сокращенный URL. http://shor.ty/cb
. Реверс еще проще. Вы просто выполняете обратный поиск в своем алфавите.
[4,61,0]
= 4 × 622 + 61 × 621 + 0 × 620 = 1915810 WHERE id = 19158
и выполните перенаправление. typedef typename Tail::inUnion<U> dummy;
Однако я не уверен, что реализация inUnion верна. Если я правильно понимаю, этот класс не должен быть создан, поэтому вкладка «fail» никогда не будет автоматически терпеть неудачу. Возможно, было бы лучше указать, находится ли тип в объединении или нет с простым булевым значением.
template <typename T, typename TypeList> struct Contains;
template <typename T, typename Head, typename Tail>
struct Contains<T, UnionNode<Head, Tail> >
{
enum { result = Contains<T, Tail>::result };
};
template <typename T, typename Tail>
struct Contains<T, UnionNode<T, Tail> >
{
enum { result = true };
};
template <typename T>
struct Contains<T, void>
{
enum { result = false };
};
PS: Посмотрите на Boost :: Variant
PS2: посмотрите на typelists , особенно в книге Андрея Александреску: Modern C ++ Design