為什么在專門的函式模板中將字串文字傳遞給const char* const&是非法的,而傳遞給const char*是合法的?
事情就是這樣。C Primer 中有兩個關于模板特化的練習:
練習 16.63:定義一個函式模板來計算給定值在向量中出現的次數。通過傳遞一個雙精度向量、一個整數向量和一個字串向量來測驗您的程式。
練習 16.64:撰寫上一個練習中的模板的專門版本來處理 vector<const char*> 和一個使用這種專門化的程式。
下面的代碼是我的答案,當我將字串文字傳遞給這個專門的計數函式時會出現編譯錯誤。
// Count the number of occurrences of a given value in a vector
template <typename T>
std::size_t count(const std::vector<T>& vec, const T& value)
{
std::size_t i = 0;
for (const auto& v : vec) {
if (v == value)
i;
}
return i;
}
// A specialized version where T = const char*
template <>
std::size_t count(const std::vector<const char*>& vec, const char* const& value)
{
std::size_t i = 0;
for (const auto& v : vec) {
if (!strcmp(v, value))
i;
}
return i;
}
int main()
{
std::vector<const char*> sVec{ "cpp", "primer", "cpp", "fifth", "edition", "Cpp", "cpp" };
// Error message: no instance of function template "count" matches the argument list,
// argument types are: (std::vector<const char *, std::allocator<const char *>>, const char [4])
std::cout << count(sVec, "cpp") << std::endl;
return 0;
}
此外,在非模板函式中將字串文字傳遞給const char* const&是完全可以的,這讓我感到困惑。
void test(const char* const& str)
{
std::cout << str << std::endl;
}
int main()
{
test("cpp"); // Prints "cpp" as expected
return 0;
}
uj5u.com熱心網友回復:
您不會“傳遞給函式模板專業化”。該呼叫是根據原始模板定義推匯出來的(不管任何特化),如果成功則推匯出一個型別。然后,如果推導的型別存在特化,則將呼叫該特化。
錯誤訊息是關于 type deduction failed 。即使您洗掉專業化,您也應該看到完全相同的錯誤。
型別推導失敗,因為T發生在兩個不同的引數中,但每個引數的推導結果不同:
vector<T>& vec對vector<const char *>產生的推論T=const char *const T& value對"cpp"產生的推論T=const char[4]。
T只有當所有被推導的實體都產生相同的型別時,推導才會成功。通過考慮可用的轉換來協調不同型別的額外步驟。
解決問題的一種方法是使用多載而不是專門化(即洗掉文本template <>)。然后是由非模板函式和推導結果(如果有)組成的多載集。如果推演失敗了,這不是錯誤,因為多載集仍然包含某些內容。
uj5u.com熱心網友回復:
陣列和指標是不同的型別。
由于默認轉換,您可以將陣列作為指標引數傳遞。
模板就是這樣,一個函式的“模板”。
沒有具體的函式來匹配已指定的引數。所以編譯器試圖從引數中生成一個函式并且無法進行匹配,所以它失敗了。
但是當您指定模板引數時,編譯器確切地知道您想要哪個函式,生成它,然后嘗試使用呼叫函式的標準規則來呼叫該函式,從而允許它進行轉換。
當您有模板函式定義時,對函式引數的要求更嚴格。
在這種情況下,它將嘗試匹配陣列并從模板生成函式并失敗。所以沒有函式可以呼叫。
你可以專攻:
// A specialized version where T = const char[ArraySize]
template<std::size_t ArraySize>
std::size_t count(const std::vector<const char*>& vec, const char (&value)[ArraySize])
{
return count<const char*>(vec, value);
}
- 編輯
或者專門定義一個模板引數函式,它定義了一個具體的函式來呼叫。
uj5u.com熱心網友回復:
哦,我將代碼更改為std::cout << count<const char*>(sVec, "cpp") << std::endl;然后一切都很好。似乎編譯器將字串文字“cpp”視為const char [4]而不是const char* const&,因此我必須明確指定模板引數。想知道為什么會這樣。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/430749.html
上一篇:在c中列印char指標值
