我正在尝试推导出一种真正独立于底层字符串类型的字符串算法编写技术。
背景:GetIndexOf 和 FindOneOf 的原型(prototype)是重载或模板化的变体:
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 *)
在尝试解决这两个目标时,我认为我可以使用某种类型选择器来即时派生出正确的接口(interface):
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)。
但这种方法的问题在于,当 str 是 CStringT<> 时,T 是 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<>(和其他类似的模板函数),其中参数是字符串(不是一对( , end] arguments),然后根据该字符串参数类型(const * 或 const CString<> &)生成的模板是正确的。
所以问题是:我如何编写 FindIndexOfOneOf<> 使其参数可以是以下任何一个而无需创建底层参数的拷贝:
1. FindIndexOfOneOf(_T("abc"), _T("def"));
2. CString 字符串; FindIndexOfOneOf(str, _T("def"));
3. CString 字符串; FindIndexOfOneOf(T("abc"), str);
3. CString 字符串; FindIndexOfOneOf(str, str);
将我引向这一点的与此相关的主题:
A better way to declare a char-type appropriate CString<>
Templated string literals
最佳答案
试试这个。
#include <type_traits>
inline int FindIndexOfOneOf(T& str, const typename char_type_of<typename std::decay<T>::type>::type* pszSearchChars)
问题是,当您将第一个参数设为引用类型 T 时,推导为:
const char []
但你想要
const char*
您可以使用以下方法进行此转换。
std::decay<T>::type
If is_array<U>::value is true, the modified-type type is remove_extent<U>::type *.
关于C++ 字符串类型独立算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4306060/