c++ - 向前声明类模板显式/部分特化有什么意义?

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

C++98 标准规定:

[temp.class.spec] Partial specialization declarations themselves are not found by name lookup.

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

[temp.class.spec.match] When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations.

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

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

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>

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

这种行为有任何实际应用吗?除此之外,这些前向声明还有什么用处吗?

最佳答案

说唯一的目的是让程序无法编译是不正确的。在下文中,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>;
}

关于c++ - 向前声明类模板显式/部分特化有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17200312/

相关文章:

c++ - 在控制台应用程序中与空的 Windows 消息队列作斗争

c++ - 绘制后在自定义小部件上绘制

c++ - MSVC - 使用 void_t 进行成员检测无法正常工作

c++ - 具有方法指针参数默认值的模板

python - Django formwizard - 无法从步骤1到步骤2获取数据

c++ - 标准如何允许通过依赖的 typedef 名称继承构造函数?

转换后比较指针值,还是一样相等?

c++ - 使用额外的不可推导模板参数重载函数是否有效?

c++ - 运算符重载和继承

C++:如何在方法的顶部声明一个数组?