我对模板重载/特化解析规则的某些细节感到困惑。我试图通过Herb Sutter on template overloading/specialization的这篇文章来了解这个主题。我坚持文章中的以下具体要点。
这是
Consider the following code:
// Example 2: Explicit specialization
//
template<class T> // (a) a base template
void f( T );
template<class T> // (b) a second base template, overloads (a)
void f( T* ); // (function templates can't be partially
// specialized; they overload instead)
template<> // (c) explicit specialization of (b)
void f<>(int*);
// ...
int *p;
f( p ); // calls (c)
The result for the last line in Example 2 is just what you'd expect. The question of the day, however, is why you expected it. If you expected it for the wrong reason, you will be very surprised by what comes next. After all, "So what," someone might say, "I wrote a specialization for a pointer to int, so obviously that's what should be called" - and that's exactly the wrong reason.
Consider now the following code, put in this form by Peter Dimov and Dave Abrahams:
// Example 3: The Dimov/Abrahams Example
//
template<class T> // (a) same old base template as before
void f( T );
template<> // (c) explicit specialization, this time of (a)
void f<>(int*);
template<class T> // (b) a second base template, overloads (a)
void f( T* );
// ...
int *p;
f( p ); // calls (b)! overload resolution ignores
// specializations and operates on the base
// function templates only
我在示例2和示例3之间看到的唯一区别是模板b和c的声明顺序。我不明白为什么会有所不同。宣言的顺序与任何事情有什么关系?我一定错过了c ++的基本概念,我在文章中没有看到对此的解释。
我真的很感谢有人为我清理它。
感谢。
答案 0 :(得分:1)
在第二个示例中,class T
模板发生了特化,因为class T*
模板甚至在声明特化时尚未声明。
因此,当编译器去寻找最佳匹配模板时,它会选择正确的class T*
模板,该模板没有专门化。
答案 1 :(得分:1)
宣言的顺序与任何事情有什么关系?
专业化声明必须始终遵循专门模板的声明(14.7.3 / 3)。在示例2中,(c)是两者(a)和(b)的明确专门化。在例3中,(c)只是(a)的显式特化,因为(b)跟随它。
当执行重载解析时,模板是否具有显式特化并不重要。在这两个示例中,重载决策选择(a)上的模板(b),因为它更专业(14.5.6.2)。在示例2中,选择哪一个实际上并不重要,因为(c)是两个模板的特化,因此无论如何都会调用它。在例3中,它很重要。因为(b)胜过重载决议而(c)不是(b)的特化,所以(c)不会被调用。