声明类模板显式/部分特化的前提是什么意思?

时间:2013-06-19 20:06:34

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

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>

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

这种行为是否有任何实际的实际应用?除此之外,这些前向声明是否有用?

1 个答案:

答案 0 :(得分:4)

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