Элегантность решения с шаблонами
От: tomek Украина  
Дата: 22.03.08 10:34
Оценка:
Здравствуйте.
Мне необходимо написать класс строки , используя шаблоны. Предполагается, что будет два типа строк: юникодные и анси. Вот например даю определение:
template<typename CT>
class CTestString {
  public:
        CTestString(void);                                        
        CTestString(const LPCTSTR lpszStr);    
.................

И вот мне требуется так сделать, чтобы использовать юникодные ф-ии в случае, если я инстанциируют 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);


Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?
Re: Элегантность решения с шаблонами
От: LaptevVV Россия  
Дата: 22.03.08 11:18
Оценка:
Здравствуйте, tomek, Вы писали:

T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?

1. Почему нельзя использовать стандартные string и wstring?
2. В стандартных строках это делается с помощью класса свойств charTraits.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Элегантность решения с шаблонами (CharTraits)
От: rg45 СССР  
Дата: 22.03.08 11:18
Оценка: 3 (1)
#Имя: FAQ.cpp.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>>
--
Завтра сегодня будет вчера
Re[2]: Элегантность решения с шаблонами
От: rg45 СССР  
Дата: 22.03.08 11:22
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, tomek, Вы писали:


T>>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?

LVV>1. Почему нельзя использовать стандартные string и wstring?

Как я понял, класс строки в данной задаче не является самоцелью, а человек хочет попрактиковаться в работе с шаблонами.
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Завтра сегодня будет вчера
Re[2]: Элегантность решения с шаблонами
От: tomek Украина  
Дата: 22.03.08 12:05
Оценка: :)
Спасибо! Так и думал , что будет замут с еще одним шаблоном
Re[3]: Элегантность решения с шаблонами
От: brainunit  
Дата: 22.03.08 14:20
Оценка:
Насколько я помню, LPCTSTR выводится на основе директивы препроцессора UNICODE, т.е. переключение между unicode/ansi происходит на этапе компиляции. Поэтому Вы можете написать что-то вроде этого:
#ifdef UNICODE
...
#else
...
#endif
Re: Элегантность решения с шаблонами
От: Kluev  
Дата: 24.03.08 07:18
Оценка: 1 (1) +1
Здравствуйте, tomek, Вы писали:

T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?


Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.

size_t str_len(const char *s) {return strlen(s)};
size_t str_len(const wchar_t *s) {return wcslen(s)};
Re[2]: Элегантность решения с шаблонами
От: Alex Alexandrov США  
Дата: 04.04.08 18:38
Оценка: :)
Здравствуйте, 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)
Re[2]: Элегантность решения с шаблонами
От: Erop Россия  
Дата: 04.04.08 19:03
Оценка:
Здравствуйте, Kluev, Вы писали:

K>Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.


Как вариант, можно написать шаблонные функции, а для этих типов их перекрыть и вызвать функции из crt
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Элегантность решения с шаблонами
От: MindWrapper  
Дата: 06.04.08 09:51
Оценка:
AA>В любом большом проекте (или почти любом) наберется с десяток реализаций строк. Почему? Да потому что каждый думает: "Блин, задолбали эти N реализаций строк. Сейчас напишу самую хорошую и все на нее перейдут". И реализаций становится N+1.

100%! до боли знакомая ситуация. Релизация которая мне попадалась была оболочкой на std::string, причем, для "удобтва", был реализоавн оператор примедения к const char*. ужас! Еще частенько самопальными timestamps грешат
Re: Элегантность решения с шаблонами
От: Ligen Украина http://zone-of-ambiguity.blogspot.com/
Дата: 06.04.08 10:35
Оценка:
T>Здравствуйте.
T>Мне необходимо написать класс строки , используя шаблоны. Предполагается, что будет два типа строк: юникодные и анси. Вот например даю определение:

// проскипано

T>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?


я, как правило, использую в таких случаях traits:

template<class Type>
struct cts_traits
{
};

template<>
struct cts_traits<char>
{
    typedef char * pointer;
    typedef const char * const_pointer;
    static inline size_t used_strlen(const_pointer pStr) { return strlen(pStr); }
};

template<>
struct cts_traits<wchar_t>
{
    typedef wchar_t * pointer;
    typedef const wchar_t * const_pointer;
    
    static inline size_t used_strlen(const_pointer pStr) { return wcslen(pStr); }
};


template<typename CT>
class CTestString 
{
      typename cts_traits<CT>::pointer m_sString;
  public:
      CTestString(void);                                        

      
      void Smth()
      {
          cts_traits<CT>::used_strlen(m_sString);
      }
};
Viva el Junta Militar! Viva el Presidente!
Re[4]: Элегантность решения с шаблонами
От: Erop Россия  
Дата: 06.04.08 13:06
Оценка:
Здравствуйте, MindWrapper, Вы писали:

MW>100%! до боли знакомая ситуация. Релизация которая мне попадалась была оболочкой на std::string, причем, для "удобтва", был реализоавн оператор примедения к const char*. ужас! Еще частенько самопальными timestamps грешат


У всех свои представления об удобстве, вообще-то.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Элегантность решения с шаблонами
От: rg45 СССР  
Дата: 07.04.08 10:03
Оценка: 1 (1)
Здравствуйте, Kluev, Вы писали:

K>Здравствуйте, tomek, Вы писали:


T>>Нутром чувствую, что маразм пишу, — вернее, некрасиво и примитивно — но как по иному — не представляю. Кто-нибудь подскажет, как правильно в таким случаях пишут?


K>Тебе нужно написать нормальные перегруженные функции. И в шаблонном коде вызывать их. Компилер по типу аргумента сам разберется.


K>
K>size_t str_len(const char *s) {return strlen(s)};
K>size_t str_len(const wchar_t *s) {return wcslen(s)};
K>


В данном случае это будет наиболее простым решением. Но если говорить вообще, то использование Traits может иметь следующие преимущества:
--
Завтра сегодня будет вчера
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.