簡體   English   中英

實例化模板時,其不完整參數類型的成員是否應該可見?

[英]When instantiating a template, should members of its incomplete argument types be visible?

在以下示例中, A具有成員typedef Instantiate ,該實例導致B<A>的實例化。

template<typename T>
struct B
{
    typedef typename T::Before Before; // ok
    typedef typename T::After After; // error: no type named 'After' in 'A<int>'
};

template<typename T>
struct A
{
    typedef int Before;
    typedef typename B<A>::After Instantiate;
    typedef int After;
};

template struct A<int>; // instantiate A<int>

我試過的所有編譯器都報告說,雖然A::Before是可見的,但A::After不是。 這種行為是否符合標准? 如果是這樣,標准在哪里指定在實例化B<A>期間A哪些名稱應該是可見的?

如果依賴名稱“在模板實例化時查找”,那么在由模板參數(例如T::After限定的名稱的場景中,這意味着什么?

編輯:請注意,當A不是模板時,會發生相同的行為:

template<typename T>
struct B
{
    typedef typename T::Before Before; // ok
    typedef typename T::After After; // error: no type named 'After' in 'A'
};

struct A
{
    typedef int Before;
    typedef B<A>::After Instantiate;
    typedef int After;
};

..和G ++接受以下內容,但Clang沒有:

template<typename T>
struct B
{
    static const int value = 0;
    static const int i = T::value; // clang error: not a constant expression
};

struct A
{
    static const int value = B<A>::value;
};

編輯:經過一些C ++ 03標准的閱讀:

[temp.dep.type]如果類型是模板參數,則該類型是相關的

因此T是依賴的。

[temp.res]在查找模板定義中使用的名稱聲明時,通常的查找規則用於非依賴名稱。 依賴於模板參數的名稱查找被推遲,直到知道實際模板參數。

因此推遲T::After的查找,直到知道T的參數為止。

[temp.inst]除非已顯式實例化類模板特化,否則在需要完全定義的對象類型的上下文中引用特化時,將隱式實例化類模板特化。

因此, A<int>::Instantiate的聲明需要實例化B<A> (因為它在嵌套名稱說明符中使用。)

A<int>::After在聲明A<int>::Instantiate是不可見的,所以編譯器的行為是有意義的 - 但是我沒有在C ++ 03中看到任何明確描述這種行為的東西。 最接近的是這個有點模糊的段落:

[temp.dep.res]在解析依賴名稱時,會考慮以下來源的名稱:

- 在模板定義點可見的聲明。

是否有typename T::Before有效未被規范明確說明。 它是缺陷報告的主題(因為可以非常合理地閱讀標准以禁止它): http//www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287

typename T::After是否無效也可以通過規范非常合理地讀取,實際上它有點意義(並且前面提到的DR仍然使其不正確)。 因為你有一個類A<Foo>的實例化,它在一個尚未聲明成員Baz的時間段內引用另一個類A<Bar> ,並且引用回A<Foo>::Bar 這是病態的非模板藏漢的情況下(試圖“忘記”您所處理的模板了一下:肯定的查找B<A>::AfterA模板完全解析,但是在完全創建它的特定實例化之后卻沒有 。實際上它將實例化它的實例化!)。

struct A {
   typedef int Foo;
   typedef A::Foo Bar; // valid
   typedef A::Baz Lulz; // *not* valid
   typedef int Baz; 
};

由於[temp.dep.type] / 8和/ 5, T::BeforeT::After是從屬名稱。

在模板定義的上下文和實例化的上下文中,在模板實例化(14.6.4.1)處查找從屬名稱。“ [temp.dep] / 1

我將其解釋為:在實例化模板時查找它們。 他們在哪里抬頭? 在模板定義的上下文和實例化的上下文中。

[temp.dep.type] / 7另一方面說:

如果對於一個給定的模板參數,模板的特化實例化是指與一個合格的-ID或類成員訪問表達式,在合格-ID或類成員訪問表達式的名稱是當前實例中的一員在模板實例化上下文中查找。

[temp.point] / 7定義實例化上下文 ,如下所示:

依賴於模板參數的表達式的實例化上下文是在同一翻譯單元中模板特化的實例化之前聲明的具有外部鏈接的聲明集。

因此,我們需要知道實例化的重點。

[temp.point / 4

對於類模板特化[...],如果特化是隱式實例化的,因為它是從另一個模板特化中引用的,如果引用特化的上下文取決於模板參數,並且如果特化沒有實例化,則對於封閉模板的實例化,實例化的點緊接在封閉模板的實例化之前。

雖然注入的類名 A可以說是 依賴於 (作為外行術語) A的模板參數的上下文,但名稱 A本身不是依賴名稱。 Johannes Schaub的更正:這一個從屬名稱。 參見[temp.local] / 1和[temp.dep.type] / 8 => A是從屬類型。

因此,該條件 不滿足 ,和B<A>應之前被實例A<int>

暫無
暫無

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

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