簡體   English   中英

為什么我不能在這個專門的 function 模板中將字符串文字傳遞給 const char* const&

[英]Why I can't pass string literals to const char* const& in this specialized function template

為什么在專門的 function 模板中將字符串文字傳遞給const char* const&是非法的,而傳遞給const char*是合法的?

事情是這樣的。 C++ Primer中有兩個關於模板特化的練習:

練習 16.63:定義一個 function 模板來計算給定值在向量中出現的次數。 通過向程序傳遞一個雙精度向量、一個整數向量和一個字符串向量來測試您的程序。

練習 16.64:編寫上一個練習中模板的專用版本來處理 vector<const char*> 和一個使用該專用化的程序。

下面的代碼是我的答案,當我將字符串文字傳遞給這個專門的計數function 時出現編譯錯誤。

// 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;
}

此外,在非模板 function 中將字符串文字傳遞給const char* const&是完全可以的,這讓我感到困惑。

void test(const char* const& str)
{
    std::cout << str << std::endl;
}

int main()
{
    test("cpp"); // Prints "cpp" as expected
    return 0;
}

數組和指針是不同的類型。

由於默認轉換,您可以將數組作為指針參數傳遞。

模板就是 function 的“模板”。

沒有具體的function來匹配已經指定的參數。 所以編譯器試圖從參數中生成一個 function 並且無法匹配,所以它失敗了。

但是當你指定模板參數時,編譯器確切地知道你想要哪個 function,生成它,然后嘗試使用調用函數的標准規則調用 function,這允許它進行轉換。

當你有模板 function 定義時,對 function arguments 的要求更嚴格。

在這種情況下,它將嘗試匹配數組並從模板生成 function 並失敗。 因此無法撥打 function。

你可以專攻:

// 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);
}

- 編輯

或者專門定義一個模板參數function,里面定義了一個具體的function來調用。

您不會“傳遞給 function 模板專業化”。 該調用是根據原始模板定義推導出來的(不管任何專業化),如果成功則推導出一個類型。 然后,如果推導類型存在專門化,則將調用該專門化。

錯誤消息是關於類型推導失敗的。 即使刪除專業化,您也應該看到完全相同的錯誤。

類型推導失敗,因為T出現在兩個不同的參數中,但推導結果因每個參數而異:

  • 根據vector<const char *>推導vector<T>& vec產生T=const char *
  • 根據"cpp"推導const T& value產生T=const char[4]

僅當推導的T的所有實例都產生相同類型時,推導才會成功。 沒有通過考慮可用轉換來協調不同類型的額外步驟。

解決該問題的一種方法是使用重載而不是特化(即刪除文本template <> )。 然后是一個由非模板 function 和推導結果(如果有)組成的重載集。 如果演繹失敗,正如它所做的那樣,這不是錯誤,因為重載集仍然包含一些東西。

哦,我將代碼更改為std::cout << count<const char*>(sVec, "cpp") << std::endl; 然后一切都很好。 編譯器似乎將字符串文字 "cpp" 視為const char [4]而不是const char* const& ,因此我必須明確指定模板參數。 想知道為什么會這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM