我已經測驗了這幾個模板以顯示模板實體化的有效性:
template <typename T>
using LRef = T&;
template <typename T>
using Ptr = T*;
template <typename>
requires false
class A {};
// ...
using T0 = LRef<int>; // expected ok
// using T1 = LRef<void>; // expected error, forming void& which is invalid
using T2 = Ptr<void>; // expected ok
// using T3 = Ptr<int&>; // expected error, forming int& * which is invalid
// using T4 = A<int>; // expected error, unsatisfied constraint resulting in invalid instantiation
然而,
template <typename T>
struct Box { T value; };
template <typename T, typename U = T>
struct Derive : T, U {};
// ...
using T5 = Derive<int, float>; // unexpected no-error, but should be invalid
// template struct Derive<int, float>; // expected error
using T6 = Derive<Box<int>, Box<float>>; // expected ok
template struct Derive<Box<int>, Box<float>>; // expected ok
using T7 = Derive<Box<int>>; // unexpected no-error, but should be invalid
// template struct Derive<Box<int>>; // expected error
void foo() {
// T5 {}; // error
// T7 {}; // error
}
的型別別名宣告T5并且T7沒有錯誤,這是意料之外的。我認為它們應該是無效的,因為具有相同模板引數的顯式實體化和型別別名的使用存在錯誤。
這是標準 C 中的正確行為還是沒有正確實作?這 3 個主要編譯器(GCC、Clang 和 MSVC)顯示該程式沒有編譯錯誤。https://godbolt.org/z/hcbszo49a
uj5u.com熱心網友回復:
這在標準 C 中有效還是沒有正確實作?
沒有使用and的第二個片段格式正確。T5{};T7{};
這是因為typedefs,using并且不需要完全定義的型別。并且來自隱式實體化的檔案:
當代碼在背景關系中參考需要完全定義型別的模板時,或者當型別的完整性影響到代碼時,并且該特定型別沒有被顯式實體化時,就會發生隱式實體化。例如,當構造此型別的物件時,而不是構造指向此型別的指標時。
(強調我的)
并且由于 型別別名不需要完全定義的型別,根據上面參考的陳述句, a typedefor不會有隱式實體化using。
例如:
template<typename T> struct C{ T& k;};
using V = C<void>; //no implicit instantiation
int main()
{
C<int>* k;//no implicit instantiation
C<void>* l; //no implicit instantiation
};
演示
它們應該是無效的,因為具有相同模板引數的顯式實體化和型別別名的使用存在錯誤。
請注意,在您使用別名模板而不是類模板的第一個片段中,所有編譯器似乎都會產生您提到的錯誤(Demo),但這是因為它們被允許(但不是必需)這樣做,正如模板類編譯中所解釋的那樣如果無法編譯未使用的函式,則使用 C 17 但不使用 C 20。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/486482.html
