根據cppreference.com 上的模板引數和模板引數:
型別模板形參的模板實參必須是型別 ID,它可能會命名不完整的型別
這意味著此示例(從該頁面復制)是合法的:
// Example 0
template <typename T>
struct X {};
struct A;
int main() {
X<A> x1;
}
而且,我想,這也是合法的:
// Example 1
template <typename T>
struct X {};
struct A {
X<A> x1;
};
int main() {
A a1;
}
現在,讓我們把代碼復雜一點:
// Example 2
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
using type = int;
X<A>::type x1;
};
int main() {
A a1;
}
在這種情況下,A用作模板引數時仍然是不完整的型別,并且代碼可以編譯。現在,如果我更改以下行的順序A:
// Example 3
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
X<A>::type x1; // ERROR HERE
using type = int;
};
int main() {
A a1;
}
代碼不再編譯。Clang 錯誤訊息類似于no type named 'type' in 'A',但 GCC、ICC 和 MSVC 也會回傳類似的錯誤(請參閱godbolt.com 上的此演示),這似乎與 CRTP 上的 typedefs 幾乎相同,在此處討論。
無論如何,這種行為似乎是合理的:編譯器使用A定義點的所有屬性X<A>。
但是 C 14(或更高版本)標準對此有何評論?依賴作業示例 2的行為是否合法?
uj5u.com熱心網友回復:
這是CWG 第 287 期。
您可以查看那里的推理,但我的理解是,共識是目前技術上的標準不允許您的最后一個或倒數第二個示例,因為實體化X<A>點將在定義之前A, 哪里typename T::type不能形成。
然而,正如提議的決議中所指出的,即使實體化點在 的定義之前,在需要實體化的點之前A宣告的名稱仍應對實體化可見。AX<A>
這就是編譯器實作的,你觀察到的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/455268.html
下一篇:回圈內的C 單行If-Else
