1

模板类的成员函数可以是完全专用的,例如,为什么你不能部分专门化一个类成员函数?

template<class A> 
struct MyClass { 
    // Lots of other members 
    int foo(); 
}; 

template<class A> 
MyClass<A>::foo() { return 42; } 

template<> 
MyClass<int>::foo() { return 0; } 

会编译没有问题。请注意0​​不是模板函数,所以这不是模板函数专业化(我可以理解,部分专业化是不允许的,因为它会与重载结合起来令人难以置信的混淆)。在我看来,上面的代码只是为了下面的模板专业化的缩写:

template<class A> 
struct MyClass { 
    // Lots of other members 
    int foo(); 
}; 

template<class A> 
MyClass<A>::foo() { return 42; } 

template<> 
struct MyClass<int> { 
    // Copy all the other members from MyClass<A> 
    int foo(); 
}; 

template<> 
MyClass<int>::foo() { return 0; } 

这是正确的吗?

在这种情况下,我不知道为什么一个部分专业化有类似简写是不允许的,即为什么我不能写

template<class A, class B> 
struct MyClass { 
    // Lots of other members 
    int foo(); 
}; 

template<class A, class B> 
MyClass<A,B>::foo() { return 42; } 

template<class B> 
MyClass<int,B>::foo() { return 0; } 

的简写

template<class A, class B> 
struct MyClass { 
    // Lots of other members 
    int foo(); 
}; 

template<class A, class B> 
MyClass<A,B>::foo() { return 42; } 

template<class B> 
struct MyClass<int,B> { 
    // Copy all the other members from MyClass<A,B> 
    int foo(); 
}; 

template<class B> 
MyClass<int,B>::foo() { return 0; } 

由于第二个片段是合法的,第一个片段是合法的,第一个片段与其完全相同(但没有我必须明确复制所有其他数据成员并永久保持它们),我不明白为什么第一个不允许。

我知道这个问题已经被问到herehere,但我不是在寻找类型为“确实不允许”的答案。或者“这是不允许的,因为标准说不是”,也没有办法规避这个问题。我想知道为什么该标准不允许它,即是否有一个基本的原因或未来可以允许?到目前为止,我没有发现任何明显重复的问题。

+0

这个问题经常被问到。长的答案在这里:http://www.gotw.ca/publications/mill17.htm –

+0

我可能是错的,但我认为这篇文章是关于专门*模板函数*。我的问题是关于专门化*模板类*的非模板*成员函数,在我看来,它实际上专门化了类而不是函数(因为成员函数不是模板)。 – PieterNuyts

+0

MyClass (例如)是与MyClass 不同的类。尝试为成员函数专门化模板类的模板类型是没有意义的。 –

回答

3

您的第一个问题的答案 - 第二个片段是否确实等同于第一个 - 是“否”。

特别是,您的评论“//从MyClass复制所有其他成员”并不真正起作用:这些成员必须保持类模板的成员以确保它们只是“按需实例化”。否则,您很可能会在您从未实际使用过的成员中获得错误的早期错误。

(也有一个不幸的问题,在C++中并不是所有的隐式实例可以写成等效明确的分工。)

这并不意味着我们不能拿出一个规范添加类似的功能。它只比“完全专业化”更微妙,迄今为止,我还没有意识到将这个标准付诸实践的认真努力。

+0

谢谢!但是我现在有点困惑 - 我认为无论何时创建模板类的实例,都会实例化模板类的所有非模板成员。那么这是不是真的? – PieterNuyts

+1

成员只是“部分”实例化的类;即定义没有被实例化;只有声明。 (明确的部分/专业化只提供定义;它不会修改声明。) –

+0

谢谢!很高兴知道 – PieterNuyts

相关问题