<bdo id='g6Yft'></bdo><ul id='g6Yft'></ul>
      <tfoot id='g6Yft'></tfoot>
    1. <legend id='g6Yft'><style id='g6Yft'><dir id='g6Yft'><q id='g6Yft'></q></dir></style></legend>

    2. <i id='g6Yft'><tr id='g6Yft'><dt id='g6Yft'><q id='g6Yft'><span id='g6Yft'><b id='g6Yft'><form id='g6Yft'><ins id='g6Yft'></ins><ul id='g6Yft'></ul><sub id='g6Yft'></sub></form><legend id='g6Yft'></legend><bdo id='g6Yft'><pre id='g6Yft'><center id='g6Yft'></center></pre></bdo></b><th id='g6Yft'></th></span></q></dt></tr></i><div id='g6Yft'><tfoot id='g6Yft'></tfoot><dl id='g6Yft'><fieldset id='g6Yft'></fieldset></dl></div>

      <small id='g6Yft'></small><noframes id='g6Yft'>

    3. 实例化模板时,其不完整参数类型的成员是否应

      时间:2023-05-25
          <legend id='vsbZG'><style id='vsbZG'><dir id='vsbZG'><q id='vsbZG'></q></dir></style></legend>
            <tbody id='vsbZG'></tbody>

            <bdo id='vsbZG'></bdo><ul id='vsbZG'></ul>

            <i id='vsbZG'><tr id='vsbZG'><dt id='vsbZG'><q id='vsbZG'><span id='vsbZG'><b id='vsbZG'><form id='vsbZG'><ins id='vsbZG'></ins><ul id='vsbZG'></ul><sub id='vsbZG'></sub></form><legend id='vsbZG'></legend><bdo id='vsbZG'><pre id='vsbZG'><center id='vsbZG'></center></pre></bdo></b><th id='vsbZG'></th></span></q></dt></tr></i><div id='vsbZG'><tfoot id='vsbZG'></tfoot><dl id='vsbZG'><fieldset id='vsbZG'></fieldset></dl></div>

            <small id='vsbZG'></small><noframes id='vsbZG'>

              <tfoot id='vsbZG'></tfoot>

              • 本文介绍了实例化模板时,其不完整参数类型的成员是否应该可见?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                问题描述

                限时送ChatGPT账号..

                在下面的例子中,A 有一个成员 typedef Instantiate,它导致 B 的实例化.

                In the following example, A has a member typedef Instantiate which causes the instantiation of 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 中的哪些名称应该是可见的?

                All the compilers I've tried report that, while A::Before is visible, A::After is not. Is this behaviour compliant with the standard? If so, where does the standard specify which names in A should be visible during instantiation of B<A>?

                如果依赖名称是在模板实例化点查找",那么在名称由模板参数(例如 T::After)限定的情况下,这意味着什么?

                If dependent names are "looked up at the point of the template instantiation", what does this mean in the scenario of a name qualified by a template parameter such as T::After?

                请注意,当 A 不是模板时会发生相同的行为:

                Note that the same behaviour occurs when A is not a template:

                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 不接受:

                .. and G++ accepts the following, but Clang does not:

                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 标准之后:

                After some reading of the C++03 standard:

                [temp.dep.type] 一个类型是依赖的,如果它是一个模板参数

                [temp.dep.type] A type is dependent if it is a template parameter

                因此 T 是依赖的.

                [temp.res] 在查找模板定义中使用的名称的声明时,通常的查找规则用于非依赖名称.依赖模板参数的名称查找被推迟到实际模板参数已知.

                [temp.res] When looking for the declaration of a name used in a template definition, the usual lookup rules are used for nondependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known.

                T::After 的查找因此被推迟,直到 T 的参数已知.

                The lookup of T::After is therefore postponed until the argument for T is known.

                [temp.inst] 除非已显式实例化类模板特化……当在需要完全定义的对象类型的上下文中引用特化时,类模板特化会被隐式实例化.

                [temp.inst] Unless a class template specialization has been explicitly instantiated ... the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type.

                因此 A<int>::Instantiate 的声明需要 B<A> 的实例化(因为它用于嵌套名称说明符.)

                Therefore the declaration of A<int>::Instantiate requires the instantiation of B<A> (because it is used in a nested-name-specifier.)

                A<int>::AfterA<int>::Instantiate 的声明点不可见,所以编译器的行为是有道理的 -但我在 C++03 中没有看到任何明确描述这种行为的内容.最接近的是这个有点模糊的段落:

                A<int>::After is not visible at the point of declaration of A<int>::Instantiate, so the behaviour of the compiler makes sense - but I haven't seen anything in C++03 that explicitly describes this behaviour. The closest thing was this somewhat vague paragraph:

                [temp.dep.res]在解析依赖名称时,会考虑来自以下来源的名称:

                [temp.dep.res] In resolving dependent names, names from the following sources are considered:

                ——在模板定义点可见的声明.

                — Declarations that are visible at the point of definition of the template.

                推荐答案

                typename T::Before 是否有效在规范中没有明确说明.它是缺陷报告的主题(因为可以非常合理地阅读标准来禁止它):http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287.

                Whether typename T::Before is valid is not explicitly said by the spec. It is subject of a defect report (because the Standard can very reasonably be read to forbid it): http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287 .

                typename T::After 是否无效也可以很合理地被规范读取为真的,实际上它有相当多的意义(并且前面提到的 DR 仍然保持格式错误).因为您有一个类 A 的实例化,它在成员 Baz 具有的期间引用了另一个类 A尚未声明,这会引用回 A<Foo>::Bar.在非模板的情况下,这也是格式错误的(尝试暂时忘记"您正在处理模板:B<A>::After 的查找肯定已完成A 模板被完全解析,但不是在它的具体实例化完全创建之后.实际上是它的实例化做参考!)

                Whether typename T::After is invalid can also very reasonably be read to be true by the spec, and actually it makes quite a bit of sense (and aforementioned DR still keeps it ill-formed). Because you have an instantiation of a class A<Foo>, which references another class A<Bar> during a period where a member Baz has not yet been declared, and that makes a reference back to A<Foo>::Bar. That is ill-formed in the case of non-templates aswell (try to "forget" for a moment that you are dealing with templates: surely the lookup of B<A>::After is done after the A template was completely parsed, but not after the specific instantiation of it was completely created. And it is the instantiation of it that actually will do the reference!).

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

                这篇关于实例化模板时,其不完整参数类型的成员是否应该可见?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                上一篇:使用 SFINAE 检查全局操作符<<? 下一篇:“T"和“T"之间有什么区别吗?和“const T

                相关文章

                最新文章

              • <legend id='xc460'><style id='xc460'><dir id='xc460'><q id='xc460'></q></dir></style></legend>
                    <bdo id='xc460'></bdo><ul id='xc460'></ul>

                  1. <small id='xc460'></small><noframes id='xc460'>

                    <i id='xc460'><tr id='xc460'><dt id='xc460'><q id='xc460'><span id='xc460'><b id='xc460'><form id='xc460'><ins id='xc460'></ins><ul id='xc460'></ul><sub id='xc460'></sub></form><legend id='xc460'></legend><bdo id='xc460'><pre id='xc460'><center id='xc460'></center></pre></bdo></b><th id='xc460'></th></span></q></dt></tr></i><div id='xc460'><tfoot id='xc460'></tfoot><dl id='xc460'><fieldset id='xc460'></fieldset></dl></div>
                  2. <tfoot id='xc460'></tfoot>