2010-10-31 46 views
3

考慮以下代碼:模板代碼如何在C++中查找類型爲模板參數的字符串的長度?

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的:不能從 '爲wchar_t *' 到 '爲const char *' 轉換參數1

於是我試圖用一個函數指針:

typedef size_t (*STRLEN)(void*); 
STRLEN _strlen; 
_strlen = reinterpret_cast<STRLEN> (typeid(*initStr) == typeid(char) ? strlen : wcslen); 

,並再次發出一個錯誤的編譯器,這個時間:

... \ main.cpp中(28):錯誤C2446: ':':沒有從「爲size_t(__cdecl *)(常量爲wchar_t轉換*)」到 '的size_t(__cdecl *)(爲const char *)'

我的問題是,我怎樣才能使用的功能strlenwcslen使用模板?

回答

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,在這種情況下,它是完全不合適的。

+0

正確的想法,當然PrintLength(const T * s) – CashCow 2010-10-31 15:04:53

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 
    //... 

你也可以添加你的strlen的重載爲char,那麼你不需要使用聲明。

3

您誤解了模板。您不應該使用typeid來確定類型,而是使用模板特化。

+0

是的,但是會很高興地給一個編碼例子。 Vitaut使用了一種不同的方法,具有重載功能。 – CashCow 2010-10-31 15:06:58

+0

我的第一個想法也是專業化,但是在這裏,實踐中的專業化意味着要編寫2個版本的類,這可以在沒有模板的情況下完成。 – 2010-10-31 15:26:27

+0

那麼std :: basic_string使用專門化,但不是basic_string本身,而是char_traits。 – CashCow 2010-11-01 09:53:31

1

如果OP對如何在STL中實現字符串感興趣,它們使用整個助手類調用char_traits。這是一個只有靜態成員函數的類,而char_traits專用於char和wchar_t以使用像memmove這樣的C運行時庫函數。

例如,您有一個比較函數返回值< 0,0或> 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 
相關問題