为什么函数模板不能部分特化?
我知道语言规范禁止函数模板的部分专业化。
我想知道为什么禁止这样做?它们没有用吗?
template<typename T, typename U> void f() {} //allowed!
template<> void f<int, char>() {} //allowed!
template<typename T> void f<char, T>() {} //not allowed!
template<typename T> void f<T, int>() {} //not allowed!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
AFAIK 这在 C++0x 中发生了变化。我猜这只是一个疏忽(考虑到您总是可以通过更详细的代码获得部分专业化效果,通过将函数放置为
static< /code> 类的成员)。
如果有的话,您可以查找相关的 DR(缺陷报告)。
编辑:检查这一点,我发现其他人也相信这一点,但没有人能够在标准草案中找到任何此类支持。 这个SO线程似乎表明不支持函数模板的部分专业化在 C++0x 中。
编辑2:只是我所说的“将函数作为类的
静态
成员”的含义的一个示例:AFAIK that's changed in C++0x.I guess it was just an oversight (considering that you can always get the partial specialization effect with more verbose code, by placing the function as a
static
member of a class).You might look up the relevant DR (Defect Report), if there is one.
EDIT: checking this, I find that others have also believed that, but no-one is able to find any such support in the draft standard. This SO thread seems to indicate that partial specialization of function templates is not supported in C++0x.
EDIT 2: just an example of what I meant by "placing the function as a
static
member of a class":好吧,你确实不能进行部分函数/方法特化,但你可以进行重载。
确实是这样,但不知道你是否满意。
Well, you really can't do partial function/method specialization however you can do overloading.
It is the way but I do not know if it satisfy you.
一般来说,由于重载的问题,根本不建议专门化函数模板。这是来自 C/C++ 用户期刊的一篇好文章: http://www.gotw.ca/publications /mill17.htm
它包含对您问题的诚实回答:
In general, it's not recommended to specialize function templates at all, because of troubles with overloading. Here's a good article from the C/C++ Users Journal: http://www.gotw.ca/publications/mill17.htm
And it contains an honest answer to your question:
由于您可以部分专门化类,因此可以使用函子:
Since you can partially specialize classes, you can use a functor:
由于两个原因,函数模板的部分特化会带来极大的问题。
函数模板重载的语法歧义
考虑完全特化的语法:
从
template <>
语法,很明显这是一个完全特化,而不是非模板重载。然而,对于部分特化来说就不太清楚了:
这可以解释为第二次重载,或者解释为部分特化
foo>(std::complex; )
。如果这种歧义存在于语言中,将会非常令人困惑。
当存在多个重载时,即使是完整的特化也可能会造成混乱;请参阅 定义函数模板的显式特化时选择哪个重载?
特化不参与重载解析
如果我们调用如果使用
std::complex
类型的参数,则调用 (2),而不是 (1),因为特化不参与重载解析。这是违反直觉的,因为std::complex
比std::complex
“更专业”。函数模板的完全特化和假设的部分特化的行为与直觉相反。函数模板重载是一个更有用的功能,在大多数情况下应该是首选。
解决方法 - 类模板的重载或部分特化
在大多数情况下,您可以简单地使用函数模板重载。
如果您需要紧密模仿部分特化,则可以改为编写函数对象:
与函数模板重载相比,一开始可能看起来毫无意义,但部分特化可以通过继承相互委托,这可能很有用。
这种模式是标签调度的可行替代方案。
另请参阅
Herb Sutter 的文章 为什么不专门化函数模板? 解释了有关显式专门化的问题细节。这些同样适用于假设的部分专业化。
Partial specializations of function templates would be extremely problematic for two reasons.
Syntactical ambiguity with function template overloading
Consider the syntax of a full specialization:
From the
template <>
syntax, it is clear that this is a full specialization, not a non-template overload.However, it would not be so clear for a partial specialization:
This could either be interpreted as a second overload, or as a partial specialization
foo<std::complex<T>>(std::complex<T>)
.This ambiguity would be extremely confusing if it existed in the language.
Even full specializations can be confusing when there are multiple overloads; see Which overload is selected when defining an explicit specialization of a function template?
Specializations don't participate in overload resolution
If we call this with an argument of type
std::complex<int>
, then (2) is called, not (1), because specializations don't participate in overload resolution. This is counter-intuitive becausestd::complex<int>
is "more specialized" thanstd::complex<T>
.Full specializations and hypothetical partial specializations of function templates behave contrary to intuition. Function template overloading is a much more useful feature, and should be preferred in most cases.
Workaround - Overloading, or partial specializations of class templates
In most cases, you can simply use function template overloading instead.
If you need to closely imitate partial specializations, you can write function objects instead:
It may seem pointless compared to function template overloading at first, but partial specializations can delegate to each other through inheritance, which may be useful.
Such a pattern is a viable alternative to tag dispatch.
See Also
Herb Sutter's article Why Not Specialize Function Templates? explains issues regarding explicit specializations in great detail. Those equally apply to hypothetical partial specializations.