在嘗試使用這個stackoverflow 答案時,我遇到了一個我不理解的編譯錯誤。
編譯失敗并#if 1顯示以下錯誤日志,而if 0編譯正常。
完整的錯誤日志:
Output of x86-64 gcc 11.2 (Compiler #1)
<source>: In function 'void remove(std::vector<T>&, size_t)':
<source>:8:3: error: need 'typename' before 'std::vector<T>::iterator' because 'std::vector<T>' is a dependent scope
8 | std::vector<T>::iterator it = vec.begin();
| ^~~
<source>:8:27: error: expected ';' before 'it'
8 | std::vector<T>::iterator it = vec.begin();
| ^~~
| ;
<source>:9:16: error: 'it' was not declared in this scope; did you mean 'int'?
9 | std::advance(it, pos);
| ^~
| int
<source>: In instantiation of 'void remove(std::vector<T>&, size_t) [with T = int; size_t = long unsigned int]':
<source>:25:9: required from here
<source>:8:19: error: dependent-name 'std::vector<T>::iterator' is parsed as a non-type, but instantiation yields a type
8 | std::vector<T>::iterator it = vec.begin();
| ^~~~~~~~
<source>:8:19: note: say 'typename std::vector<T>::iterator' if a type is meant
代碼(可在此處獲得):
#include <iostream>
#include <vector>
#if 1
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
std::vector<T>::iterator it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
#else
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
vec.erase(vec.begin() pos);
}
#endif
int main()
{
std::vector<int> myvector{ 1,2,3,4 };
remove(myvector, 2);
for (auto element : myvector)
std::cout << ' ' << element;
std::cout << '\n';
return 0;
}
現在,如果我按照編譯器的建議 ( typename std::vector<T>::iterator it = vec.begin();) 進行編譯,但我真的不明白typename這里為什么需要。
uj5u.com熱心網友回復:
錯誤訊息說明了一切:
錯誤:從屬名稱“
std::vector<T>::iterator”被決議為非型別,但實體化產生型別
即,雖然對于作為程式員的您來說,它顯然std::vector<T>::iterator是一種型別,但對于編譯器來說它不是,并且缺少前導typename意味著它將依賴名稱決議iterator為非型別,但是在實體化函式模板時,因此其blueprinted定義T為int,std::vector<T>::iterator決議為(別名構件宣告)型別std::vector<int>::iterator。
而為 C 20 引入的P0634R3 ( Down with typename! ):
[...] 不再需要通過 typename 關鍵字從幾個已經明確的地方消除依賴名稱作為型別名的歧義
上面的例子不是這樣的地方/背景關系。要了解為什么編譯器無法為 all 明確解決此問題T,請參閱此答案末尾的示例。
如果有的話,這是由于函式定義的冗長方法導致的編譯錯誤。不需要在迭代器變數的宣告中包含依賴名稱:
void remove(std::vector<T>& vec, size_t pos)
{
auto it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
template<typename T>
struct Evil {
using iterator = T*;
};
template<>
struct Evil<int> {
static constexpr int iterator{42};
};
template<typename T>
void f() {
static_cast<void>(Evil<T>::iterator);
}
int main() {
f<int>(); // well-formed by evil explicit specialization
f<char>(); // ill-formed by primary template where `iterator` is a type
// error: missing 'typename' prior to dependent type name 'Evil<char>::iterator'
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/410778.html
標籤:
