【问题标题】:What's the point of forward declaring a class template explicit/partial specialization?向前声明类模板显式/部分特化有什么意义?
【发布时间】:2013-06-16 12:33:19
【问题描述】:

C++98 标准说:

[temp.class.spec] 通过名称查找找不到部分特化声明本身。

如果对于显式特化也是如此,则这会使类模板显式/部分特化的前向声明不可见。

[temp.class.spec.match] 当在需要类实例化的上下文中使用类模板时,有必要确定是使用主模板还是部分模板之一生成实例化专业。

这意味着直到匹配特化的(隐式)实例化点才进行显式/部分特化的选择 - 这仅在需要完全定义类时发生。

在以下示例中,前向声明的显式特化的唯一影响是使程序无法编译。

namespace N
{
    template<class T>
    struct S
    {
    };

    typedef S<char> Type; // name lookup finds S<T>

    template<>
    struct S<char>; // invisible to name lookup

    typedef S<char> Type; // name lookup finds S<T>

    int f(S<char>*); // name lookup finds S<T>

    S<int> object; // implicitly instantiates S<int>

    template<>
    struct S<int>; // illegal, explicit specialization after instantiation
}

N::S<char>* p = 0; // name lookup finds N::S<T>
int i = f(p); // name lookup finds N::f via ADL


N::S<char> object; // illegal, incomplete type N::S<char>

在这两种情况下,使程序编译的唯一方法(除了删除特化)是为这两个特化提供定义它们被实例化 - 这使得前向声明有点毫无意义。

这种行为在现实世界中有什么实际应用吗?除此之外,这些前向声明还有什么用处吗?

【问题讨论】:

  • S&lt;char&gt; 的前向声明使您不可能错误地编译一个实例化object 的通用模板的程序 - 这不是一个实际应用吗?
  • 部分专业化声明本身无法通过名称查找找到。 相反,当使用主模板名称时,还会考虑任何先前声明的主模板的部分特化
  • 我真的不明白这个问题......为什么你想向前声明一个专业?只是不要这样做......
  • @KerrekSB 防止主模板在不应该被实例化时被实例化?
  • @jthill:我认为这不可能。在实例化模板时,所有特化必须是已知的。

标签: c++ templates language-lawyer forward-declaration template-specialization


【解决方案1】:

唯一的目的是使程序无法编译是不正确的。在下文中,V2 是“格式错误的;不需要诊断”,而 V1 是格式正确的。

namespace N {
   template<typename T> struct A {
      friend void f(A *a) { } // would take this with V2
   };
}
void f(void*) { } // would take this with V1

namespace N {
/* V1: */ template<> struct A<int>;
}

int main() {
   N::A<int> *p;
   f(p);
}

namespace N {
/* V2: */ template<> struct A<int>;
}

【讨论】:

  • 我不能让这个打电话给f(A)coliru.stacked-crooked.com/…
  • @willj 为我工作:coliru.stacked-crooked.com/…。 GCC 正确地检测到“格式错误;不需要诊断的情况”并发出 V2 的诊断。不适用于 V1。
  • 好的,我明白了!如果第二个template&lt;&gt; A&lt;int&gt; 是一个定义,我认为这个例子会更清楚。 PS。我还是不知道怎么叫f(A)
  • 这应该是fA&lt;T&gt; 中的friend 声明:coliru.stacked-crooked.com/…
  • @casey 哎呀,真的。感谢您的发现!
猜你喜欢
  • 2021-03-24
  • 2015-05-26
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多