реализовать класс строки с пользовательским поведением - PullRequest
4 голосов
/ 04 января 2011

В одном из наших классов сэр сказал, что шаблон позволяет настраивать поведение класса, а затем он привел пример строкового класса, который с помощью нескольких строк кода мы можем настроить строковый класс из STL, например, мы можем сделать это рассматривать «a» и «z» одинаково, «b» и «y» одинаково, «c» и «x» одинаково и т. д. Схожие буквы «А» и «Z» и т. Д.

"abc" == "zyx" является верным;
"Abc" == "zyx" является ложным;
"Abc ==" Zyx "является верным;

и т.д.

Я думал о реализации такого строкового класса, но я не в состоянии это сделать. Как мы можем реализовать такой класс строки, используя шаблоны?

Ответы [ 3 ]

3 голосов
/ 04 января 2011

Это очень сложно.Все, что вам нужно, чтобы написать собственный класс traits , в частности, вам нужно извлечь его из шаблона класса char_traits<> и переопределить eq () и compare () функция (Примечание: только переопределение eq () не будет работать; даже если нет никаких изменений в переопределении compare () , вы должны записать его в свой производный класс кактакие!).Скажем, это черта класса sequence_traits и вызов вашей пользовательской строки sequence.В конце концов, строка - это последовательность символов!

Примечание: Из вашего поста я понимаю, что вы хотите, чтобы alphabets[i] == alphabets[25-i] рассматривался как один и тот же, то есть первая буква и последняя буквато же самое, второе письмо и второе последнее письмо то же самое, и так далее!

struct sequence_traits : char_traits<char>
{
    //'a' and 'z' are equal
    //'b' and 'y' are equal
    //'c' and 'x' are equal, and so on.
    //that implies, 'a' + 'z' == 'b' + 'y' == 'c' + 'x' == 'd'  + 'w == so on
    //same for upper cases!
    static bool eq(const char& left, const char& right)
    {   
        return ( left == right) || (left + right == 'a' + 'z') || ( left + right == 'A' + 'Z') ;
    }
    static int compare(const char *first1, const char *first2, size_t count)
    {   
        for (; 0 < count; --count, ++first1, ++first2)
            if (!eq(*first1, *first2))
                return (lt(*first1, *first2) ? -1 : +1);
        return (0);
    }
};

И тогда вы можете сделать это typedef для простоты использования:

typedef basic_string<char, sequence_traits> sequence;

Все готово.Вы можете использовать sequence сейчас.: -)

Рабочий пример: http://www.ideone.com/ByBRV


Прочтите эту статью, чтобы узнать, как это работает в деталях: http://www.gotw.ca/gotw/029.htm

2 голосов
/ 04 января 2011

Вы хотите создать свой пользовательский char_traits и создать экземпляр std::basic_string с этим.

2 голосов
/ 04 января 2011

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

class CustomTraits { ... };
typedef basic_string<char, CustomTraits> CustomString;

И теперь черты, определенные в CustomTraits, будут использоваться для определения того, как работает строка.Например, в соответствии с тем, что вы говорили, вы можете сделать что-то вроде этого:

class CustomTraits: public char_traits<char> {
public:
    /* Redefine equality to compare 'a' and 'z' equal. */
    static bool eq(char one, char two) {
         return one == two || (one == 'a' && two == 'z' || one == 'z' && two == 'a');
    }
};
typedef basic_string<char, CustomTraits> StringWithAAndZEqual;

Теперь вы можете использовать новый тип, и класс будет обрабатывать 'a' и 'z' одинаково.1011 *

...