[英]Why is explicit specialization of a class template member function allowed when defined within the class declaration, but not when defined separately?
I have seen a number of StackOverflow posts which say that specialization of a class template member function is not legal within C++, unless the enclosing class is also specialized. 我已经看到一些StackOverflow帖子,它们认为类模板成员函数的特化在C ++中是不合法的,除非封闭类也是专用的。
However, another post seemed to indicate that it is possible to specialize the member template function, just so long as the definition of the specialized function appears inside the class declaration of the template class, as follows: 然而,另一篇文章似乎表明,有可能专门的成员模板功能,只需只要出现在模板类的类声明中专门函数的定义如下:
template<typename T1, typename T2>
class A
{
public:
template<typename TX> TX foo() {return 0;};
template<> T1 foo<T1>() {return 1;}; // provide the specialization's definition within the class declaration: works
//template<> T1 foo<T1>(); // ... switch to this (and provide the definition below), and it's a compile error
};
// This function definition is only present when the commented-out line of code in the class declaration is used
template<typename T1, typename T2>
template<>
T1 A<T1, T2>::foo<T1>()
{
return 1;
}
int main(void)
{
A<int, double> a;
const int n = a.foo<int>(); // When the definition appears inside the class declaration, n is 1 - it works
return 0;
}
As you can see from the comments in my code sample, when the specialized function's definition is provided within the class declaration, the code builds without error, and furthermore it runs successfully, and the value of n
in function main()
is 1
, as expected. 从我的代码示例中的注释中可以看出,当在类声明中提供专用函数的定义时,代码构建没有错误,而且它运行成功,函数
main()
的n
值为1
,如预期。
However, when moving the specialized function definition outside the class declaration, but otherwise keeping it the same, as shown, the compiler emits the error that other posts have already pointed out; 但是,当在类声明之外移动专用函数定义时,如果保持相同,如图所示,编译器会发出其他帖子已经指出的错误; in my case (Visual Studio 2010), the error is
an explicit specialization of a template member must be a member of an explicit specialization
. 在我的情况下(Visual Studio 2010),错误是
an explicit specialization of a template member must be a member of an explicit specialization
。
My question is this. 我的问题是这个。 If explicit specializations of member functions in class templates is not allowed unless the enclosing template class is also specialized, then why does it work in my sample code if the definition is provided inside the class declaration?
如果类模板中的成员函数的显式特化是不允许的,除非封闭模板类也是专用的,那么为什么它在我的示例代码中工作,如果在类声明中提供了定义?
None of the two versions should compile for different reasons. 这两个版本都不应该出于不同的原因进行编译。
In the first case, specializations must be present at namespace level, which means that the specialization provided within the class definition should be rejected by the compiler. 在第一种情况下,必须在命名空间级别存在特化,这意味着编译器应拒绝类定义中提供的特化。
In the second case, location of the specialization is correct, but to provide a specialization of a member function (specializations of functions must always be full, never partial) you need to also fix the enclosing template class arguments. 在第二种情况下,专门化的位置是正确的,但是为了提供成员函数的特化(函数的特化必须始终是完整的,从不是部分的),您还需要修复封闭的模板类参数。 That is, you cannot specialize
foo
for a type X
regardless of which types T1
and T2
are used to instantiate the enclosing template. 也就是说,无论使用哪种类型
T1
和T2
来实例化封闭模板,都无法为类型X
专门化foo
。 You are allowed (probably not what you want) to provide an specialization with all parameters fixed: 您被允许(可能不是您想要的)提供所有已修复参数的专业化:
template <> template <>
int A<int, double>::foo<int>() { return 5; }
The alternatives that you can use are: 您可以使用的替代方案是:
example: 例:
// inside class template:
private:
template <typename T> T foo_impl( T* _ ) {...} // generic
T1 foo_impl( T1 * _ ) {...} // concrete
public:
template <typename T> T foo() {
return foo_impl( (T*)0 );
}
This way you turn a template only on the return type into a call to a function that is overloaded, and you can let the compiler resolve the problem for you. 这样,您只需将返回类型的模板转换为对重载函数的调用,您就可以让编译器为您解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.