2

的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> 

在这两种情况下,为了使程序编译(除了删除专业化)的唯一途径就是两个特例他们被实例化之前提供了一个定义 - 这使得正向声明有点无意义。

此行为是否有任何实际的实际应用?除此之外,这些前瞻性陈述是否有用?

+2

的向前声明单曲',不可能为你正确编译实例化的通用模板的程序'object' - 是不是一个实际的应用? – Casey

+2

部分专业化声明本身不是通过名称查找找到的。 *相反,当使用主要模板名称时,主要模板的任何先前声明的部分专业化也被视为*。 –

+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>; 
} 
+0

我无法调用'f(A)':http://coliru.stacked-crooked.com/view?id=3afd64be041feb1834ea8b80669ad674-e54ee7a04e4b807da0930236d4cc94dc – willj

+0

@willj适合我:http://coliru.stacked- crooked.com/view?id=0b8f0b10bfa49a499bdc44038f31357c-e54ee7a04e4b807da0930236d4cc94dc。 GCC正确地检测到“不合格;无需诊断”的情况,并发出V2的诊断信息。不适用于V1。 –

+0

好吧,我明白了!如果第二个'template <> A '是一个定义,我认为这个例子会更清晰。 PS。我仍然无法弄清楚如何叫它'f(A)' – willj

相关问题