简体   繁体   English

为什么在类声明中定义时允许类模板成员函数的显式特化,而不是在单独定义时?

[英]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. 也就是说,无论使用哪种类型T1T2来实例化封闭模板,都无法为类型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: 您可以使用的替代方案是:

  • provide a non-template overload, instead of a template specialization (in most cases it makes more sense to provide overloads than specializations, but this might not be the case here, as you cannot overload on the return type. 提供非模板重载,而不是模板特化(在大多数情况下,提供重载比特化更有意义,但这可能不是这种情况,因为您不能在返回类型上重载。
  • move the function to a different template class and then perform partial specializations there. 将函数移动到另一个模板类,然后在那里执行部分特化。
  • perform a variant of the first option: provide a single non-specialized template to be used by clients that forwards to an internal function for which different overloads are provided 执行第一个选项的变体:提供单个非专用模板供客户端使用,转发到内部函数,为其提供不同的重载

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.

相关问题 类模板特殊成员函数显式特化 - class template special member function explicit specialization 模板类成员函数的显式特化 - explicit specialization of template class member function 模板类成员函数的显式特化 - explicit specialization of template class member function 在类模板的其他未定义成员类的显式特化中定义隐藏朋友是否合法? - Is it legal to define a hidden friend in an explicit specialization of an otherwise non-defined member class of a class template? 模板类成员特化声明 - Declaration of template class member specialization 为什么在没有专门化课程的情况下不允许成员的明确专业化? - Why is explicit specialization of a member not allowed without specializing the class? 具有不同返回类型的显式专业化模板类成员函数 - explicit specialization template class member function with different return type 限制类模板成员的显式专业化 - Constraints on explicit specialization of a member of a class template 关于 class 模板成员的显式特化的混淆 - A confusion about explicit specialization for member of class template 如何为类定义中定义的模板成员函数使用显式模板实例化? - How can I use explicit template instantiation for template member functions defined within a class definition?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM