Я пытаюсь получить технику для написания строковых алгоритмов, которая действительно не зависит от базового типа строки.
Справочная информация: прототипы для GetIndexOf и FindOneOf либо перегружены, либо являются шаблонными вариантами:
int GetIndexOf(const char * pszInner, const char * pszString);
const char * FindOneOf(const char * pszString, const char * pszSetOfChars);
Эта проблема возникает в следующей функции шаблона:
// return index of, or -1, the first occurrence of any given char in target
template <typename T>
inline int FindIndexOfOneOf(const T * str, const T * pszSearchChars)
{
return GetIndexOf(FindOneOf(str, pszSearchChars), str);
}
Цели:
1. Я хотел бы, чтобы этот код работал для CStringT <>, const char *,const wchar_t * (и должно быть тривиально для расширения до std :: string)
2. Я не хочу передавать что-либо в копии (только через const & или const *)
В попыткеРешив эти две задачи, я подумал, что смогу использовать сортировщик типов для получения правильных интерфейсов на лету:
namespace details {
template <typename T>
struct char_type_of
{
// typedef T type; error for invalid types (i.e. anything for which there is not a specialization)
};
template <>
struct char_type_of<const char *>
{
typedef char type;
};
template <>
struct char_type_of<const wchar_t *>
{
typedef wchar_t type;
};
template <>
struct char_type_of<CStringA>
{
typedef CStringA::XCHAR type;
};
template <>
struct char_type_of<CStringW>
{
typedef CStringW::XCHAR type;
};
}
#define CHARTYPEOF(T) typename details::char_type_of<T>::type
, что позволяет:
template <typename T>
inline int FindIndexOfOneOf(T str, const CHARTYPEOF(T) * pszSearchChars)
{
return GetIndexOf(FindOneOf(str, pszSearchChars), str);
}
Этодолжен гарантировать, что второй аргумент передается как const *, и не должен определять T (скорее, только первый аргумент должен определять T).
Но проблема с этим подходом состоит в том, что T, когда str является CStringT <>, является копией CStringT <>, а не ссылкой на нее: следовательно, у нас есть ненужная копия.
Попытка переписать вышеприведенное как:
template <typename T>
inline int FindIndexOfOneOf(T & str, const CHARTYPEOF(T) * pszSearchChars)
{
return GetIndexOf(FindOneOf(str, pszSearchChars), str);
}
Делает этоневозможно для компилятора (VS2008) создать правильный экземпляр FindIndexOfOneOf <> для:
FindIndexOfOneOf(_T("abc"), _T("def"));
error C2893: Failed to specialize function template 'int FindIndexOfOneOf(T &,const details::char_type_of<T>::type *)'
With the following template arguments: 'const char [4]'
Это общая проблема, с которой я столкнулся с шаблонами с момента их появления (да, я такой старый): Что по существу невозможно создать способ обработки как старых массивов в стиле C, так и более новых сущностей на основе классов (возможно, лучше всего это подчеркнуть с помощью const char [4] против CString <> &).
STLБиблиотека / std «решила» эту проблему (если ее можно назвать действительно решающей), вместо этого использовав повсюду пары итераторов вместо ссылки на саму вещь.Я мог бы пойти по этому пути, за исключением того, что это отстой IMO, и я не хочу, чтобы мой код был засорен двумя аргументами везде, где должен был бы быть должным образом обработанный единственный аргумент.подход - такой как использование некоторого вида stringy_traits - который позволил бы мне написать GetIndexOfOneOf <> (и другие подобные функции шаблона), где аргумент - это строка (не пара аргументов (Being, End]), а шаблон, которыйзатем генерируется правильно, основываясь на этом типе строкового аргумента ( const * или const CString <> & ).
Итак, вопрос: Как я могу написать FindIndexOfOneOf <> так, чтобы его аргументы могли быть любыми из следующих без создания копии базовых аргументов:
1. FindIndexOfOneOf (_T ("abc"), _T ("def"));
2. CString str; FindIndexOfOneOf (str, _T ("def"));
3. CString str; FindIndexOfOneOf (T ("abc"), str);
3. CString str;FindIndexOfOneOf (str, str);
объявления к этому, которые привели меня к этой точке:
Лучший способ объявить соответствующий тип строки CString <>
Шаблонные строковые литералы