簡體   English   中英

為什么類模板的成員函數聲明必須格式正確?

[英]Why should the member function declarations of a class template be all well-formed?

OK,假設我要檢查template參數是否具有嵌套的type / typedef XYZ。

template <class T>
struct hasXZY
{
   typedef char                  no;
   typedef struct { char x[2]; } yes;
   template <class U>
   static yes f(typename U::XYZ*);
   template <class /*U*/>
   static no  f(...);
   enum {value = sizeof(f<T>(0))==sizeof(yes)};
};

如預期般運作良好。

現在考慮一下:

template <class T>
struct hasXZY
{
   typedef char                  no;
   typedef struct { char x[2]; } yes;

   static yes f(typename T::XYZ*);
   static no  f(...);
   enum {value = sizeof(f(0))==sizeof(yes)};
};

hasXYZ<int>現在會導致編譯時錯誤。 OK,f不是模板函數。 但是另一方面,當通過hasXYZ<int>::valuehasXYZ實例hasXYZ<int>::value ,編譯器可以輕松地從候選列表中排除f(int::XYZ*) 我只是不明白為什么類模板中成員函數聲明的實例化失敗必須使整個類實例化失敗。 有任何想法嗎?

編輯:我的問題是:為什么成員函數聲明都應該格式正確? 由於編譯器僅在使用方法時實例化方法,因此為什么需要正確的聲明。 將上面的example2視為此功能的可能用例。

僅當為函數重載解決方案創建候選集時才使用SFINAE。 在第一個示例中,您正在調用重載的f()函數,由於SFINAE,第一個函數被排除了。

在第二個示例中,實例化hasXZY時,必須正確定義其所有成員,並且模板參數的替換一定不會失敗。 它適用於int :: XYZ。

由於替換失敗,成員不會被排除在班級之外。

我不是C ++語言律師,但是我會盡力而為。

在第二個示例中,成員函數必須定義良好,因為一旦為int實例化hasXZY 它們就不再是模板函數 為了使自己信服,請“手動”替換T

struct hasXYZ
{
    typedef int                   T;
    typedef char                  no;
    typedef struct { char x[2]; } yes;

    static yes f(T::XYZ*);
    static no  f(...);
    enum {value = sizeof(f(0))==sizeof(yes)};
};

int main()
{
    std::cout << hasXYZ::value << "\n";
}

並觀察到它無法編譯,並且編譯錯誤與以前相同(至少在GCC中):

foo.cc:9: error: ‘T’ is not a class or namespace

相比之下,第一個示例在手動實例化后進行編譯並按預期運行; f成員仍以U為模板。

編輯:我的問題是:為什么成員函數聲明都應該格式正確? 由於編譯器僅在使用方法時實例化方法,因此為什么需要正確的聲明。 將上面的example2視為此功能的可能用例。

當隱式實例化類模板專門化時,編譯器必須檢查該成員的完整聲明器,因為它需要了解有關該聲明的基本信息。 這樣可以增加類模板專業化的規模。

如果檢查聲明部分發現它聲明了一個數據成員,則該類的sizeof值可能會產生不同的值。 如果要聲明一個函數指針,情況就是這樣

yes (*f)(typename T::XYZ*);

C ++語言的定義方式是僅在解析整個聲明后才知道聲明的類型。

您可以爭辯說您在其中放置了靜態對象,因此在這種情況下,不需要計算它的大小。 需要名稱查找知道什么名字hasXZY<T>::f指,並有被宣布為名稱F。對於所有。 編譯器將不會實例化hasXYZ::f的定義,而只會實例化聲明的hasXYZ::f部分,以獲取其類型並將其名稱添加到類類型中以進行名稱查找。 我相信在可能可行的特殊情況下支持延遲實例化名稱聲明會使C ++編譯器和C ++規范的實現更加復雜,而沒有可比的好處。

最后,在您嘗試調用它的示例中,編譯器必須實例化聲明,因為它需要查找名稱f ,為此,它需要知道該聲明是函數還是其他東西。 因此,即使在理論上,我實際上也無法在不實例化聲明的情況下看到您的示例無法工作的方式。 請注意,無論如何,這些都不會實例化函數的定義。

暫無
暫無

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

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