模板化代码如何在C ++中找到类型为模板参数的字符串的长度?

时间:2010-10-31 09:00:14

标签: c++ templates

考虑以下代码:

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>

我的问题是,如何将模板strlenwcslen用于模板?

4 个答案:

答案 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而不是strlenwcslen,并且不要明确检查参数的类型。您也可以为其他类型编写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