Здравствуйте.
Мне необходимо написать класс строки , используя шаблоны. Предполагается, что будет два типа строк: юникодные и анси. Вот например даю определение:
И вот мне требуется так сделать, чтобы использовать юникодные ф-ии в случае, если я инстанциируют CTestString<wchar_t> some. Ну и соответственно , анси варианты в случае CTestString<char> some. Как вариант, приходит лишь идея создать в классе флаг — который установится в конструкторе, в зависимости от длины типа CT:
if (sizeof(CT)==2) m_bUnicode=true;
................
// а гдето ниже, в какойто ф-ии пишу:if (m_bUnicode) m_iLength=wcslen(m_sString); else m_iLength=strlen(m_sString);
Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
Здравствуйте, tomek, Вы писали:
T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
1. Почему нельзя использовать стандартные string и wstring?
2. В стандартных строках это делается с помощью класса свойств charTraits.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, tomek, Вы писали:
T>Здравствуйте. T>Мне необходимо написать класс строки , используя шаблоны. Предполагается, что будет два типа строк: юникодные и анси. T>И вот мне требуется так сделать, чтобы использовать юникодные ф-ии в случае, если я инстанциируют CTestString<wchar_t> some. Ну и соответственно , анси варианты в случае CTestString<char> some.
Тут можно использовать достаточно распространенный прием: все особенности, которые отличают один тип символов от другого, оформить в виде отдельного шаблонного класса CharTraits, и сделать специализации этого шаблона, для тех типов символов, которые мы собираемся использовать в шаблонном классе строки:
#include <iostream>
#include <string>
//Объявление общего шаблона traits'ы для всех типов символов
//(Только объявление, определения делаются только для конкретных типов символов)template<typename> class CharTraits;
//Определение нашего типа строки использует шаблон CharTraits,
//таким образом, оно абстрагировано от конкрктных типов символовtemplate<typename T>
class CTestString
{
typedef CharTraits<T> Traits;
public:
CTestString(const T* str)
: m(new T[Traits::Length(str) + 1])
{
Traits::Copy(m, str);
}
~CTestString()
{
delete[] m;
}
const T* Value() {return m;}
private:
T* m;
};
//Далее можем определять traits'ы для разных типов символовtemplate<>
class CharTraits<char>
{
public:
static size_t Length(const char* str) {return strlen(str);}
static void Copy(char* dst, const char* src) {strcpy(dst, src);}
};
template<>
class CharTraits<wchar_t>
{
public:
static size_t Length(const wchar_t* str) {return wcslen(str);}
static void Copy(wchar_t* dst, const wchar_t* src) {wcscpy(dst, src);}
};
//Примеры использования:int main()
{
typedef CTestString<char> String;
typedef CTestString<wchar_t> WString;
String str = "This is the ANSI string";
WString wstr = L"This is the Unicode string";
std::cout << str.Value() << std::endl;
std::wcout << wstr.Value() << std::endl;
}
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, tomek, Вы писали:
T>>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут? LVV>1. Почему нельзя использовать стандартные string и wstring?
Как я понял, класс строки в данной задаче не является самоцелью, а человек хочет попрактиковаться в работе с шаблонами.
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Насколько я помню, LPCTSTR выводится на основе директивы препроцессора UNICODE, т.е. переключение между unicode/ansi происходит на этапе компиляции. Поэтому Вы можете написать что-то вроде этого:
Здравствуйте, tomek, Вы писали:
T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, tomek, Вы писали:
T>>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут? LVV>1. Почему нельзя использовать стандартные string и wstring? LVV>2. В стандартных строках это делается с помощью класса свойств charTraits.
В любом большом проекте (или почти любом) наберется с десяток реализаций строк. Почему? Да потому что каждый думает: "Блин, задолбали эти N реализаций строк. Сейчас напишу самую хорошую и все на нее перейдут". И реализаций становится N+1.
It's kind of fun to do the impossible (Walt Disney)
Здравствуйте, Kluev, Вы писали:
K>Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.
Как вариант, можно написать шаблонные функции, а для этих типов их перекрыть и вызвать функции из crt
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
AA>В любом большом проекте (или почти любом) наберется с десяток реализаций строк. Почему? Да потому что каждый думает: "Блин, задолбали эти N реализаций строк. Сейчас напишу самую хорошую и все на нее перейдут". И реализаций становится N+1.
100%! до боли знакомая ситуация. Релизация которая мне попадалась была оболочкой на std::string, причем, для "удобтва", был реализоавн оператор примедения к const char*. ужас! Еще частенько самопальными timestamps грешат
T>Здравствуйте. T>Мне необходимо написать класс строки , используя шаблоны. Предполагается, что будет два типа строк: юникодные и анси. Вот например даю определение:
// проскипано
T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
Здравствуйте, MindWrapper, Вы писали:
MW>100%! до боли знакомая ситуация. Релизация которая мне попадалась была оболочкой на std::string, причем, для "удобтва", был реализоавн оператор примедения к const char*. ужас! Еще частенько самопальными timestamps грешат
У всех свои представления об удобстве, вообще-то.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Kluev, Вы писали:
K>Здравствуйте, tomek, Вы писали:
T>>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
K>Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.
K>
В данном случае это будет наиболее простым решением. Но если говорить вообще, то использование Traits может иметь следующие преимущества:
1. Traits можно сделать параметром шаблона с возможностью использования как по умолчанию, так и с явным заданием;
2. В реализации использующего кода могут потребоваться не только функции, а также и другие сущности: типы и константы;
3. Использзование Traits делает код более самодокументированным — по существующему комлекту легко создать новый;
4. Новые Traits можно реализовывать с использованием существующих (возможно, даже с применением наследования).
5. Если Trats оформлены как шаблонный класс, в некоторых случаях может оказаться очень полезным применение частичной специализации.
--
Не можешь достичь желаемого — пожелай достигнутого.