考虑以下代码:
template <typename T>
class String
{
public:
...
String(T* initStr)
{
size_t initStrLen;
if (initStr != NULL)
{
printf_s("%s\n", typeid(T) == typeid(char) ? "char" : "wchar_t");
if (typeid(T) == typeid(char))
{
strlen((T*)initStr);
}
else if (typeid(T) == typeid(wchar_t))
{
wcslen((T*)initStr);
}
}
}
...
};
当我编译代码时,我收到了以下错误消息:
... \ main.cpp(32):错误C2664:'strlen':无法将参数1从'wchar_t *'转换为'const char *'
然后我尝试使用函数指针:
typedef size_t (*STRLEN)(void*);
STRLEN _strlen;
_strlen = reinterpret_cast<STRLEN> (typeid(*initStr) == typeid(char) ? strlen : wcslen);
再次编译器发出错误,这次:
... \ main.cpp(28):错误C2446:':':没有从'size_t(__ cdecl *)(const wchar_t *)'转换为'size_t(__ cdecl *)(const char *)'< / p>
我的问题是,如何将模板strlen
和wcslen
用于模板?
答案 0 :(得分:7)
你可以这样做,例如通过引入如下所示的辅助函数:
#include <iostream>
#include <string.h>
size_t GetLength(const char* s) { return strlen(s); }
size_t GetLength(const wchar_t* s) { return wcslen(s); }
template <typename T>
void PrintLength(T s)
{
std::cout << GetLength(s) << std::endl;
}
int main()
{
PrintLength("abc");
PrintLength(L"abc");
}
使用此辅助函数GetLength
而不是strlen
或wcslen
,并且不要明确检查参数的类型。您也可以为其他类型编写GetLength
的重载,例如: std::string
。
您很少需要在实践中使用typeid
,在这种情况下,这是完全不合适的。
答案 1 :(得分:5)
您不能使用if语句来控制为模板实例化的代码:正文中的所有代码都必须适用于每个实例化。
std::size_t strlen(wchar_t const *s) {
return std::wcslen(s);
}
//...
String(T* initStr) {
using std::strlen; // bring into scope so unqualified call can find it
std::size_t length = strlen(initStr); // uses std::strlen or our strlen
//...
您还可以为char添加strlen的重载,然后您不需要using声明。
答案 2 :(得分:3)
你误解了模板。您不应该使用typeid
来确定此处的类型,而是使用模板专门化。
答案 3 :(得分:1)
如果OP对如何在STL中实现字符串感兴趣,则它们使用整个辅助类调用char_traits。这是一个只有静态成员函数的类,char_traits专门用于char和wchar_t以使用像memmove这样的C运行时库函数。
例如,您有一个比较函数,它返回一个值&lt; 0,0或&gt; 0。如果类型为char,则可以使用memcmp。如果类型是wchar_t,它可以使用宽的等价物。
它的工作原理如下:
template< typename Element >
class char_traits
{
public:
static int compare( const Element * left, const Element * right, size_t length )
{
for( const Element * end = left + length; left != end; ++left )
{
if( left < right )
return -1;
else if( left > right )
return 1;
}
return 0;
}
// other functions
};
template <> class char_traits<char> // I think this is the syntax
{
public:
int compare( const char * left, const char * right, size_t len )
{
return memcmp( left, right, len ); // more efficient than the general loop above
}
// other functions
};
// specialise also for wchar_t