我以为会调用具有最具体的匹配参数类型的函数重载,但我似乎不理解模板和继承类型组合时类型推导的一个方面。
例子:
#include<iostream>
#include<typeinfo>
struct Foo {};
struct Bar : Foo {};
#ifdef FOO
void print_typeid( const Foo& f ) {
std::cout << "(F) typeid: " << typeid(f).name() << std::endl;
}
#endif // FOO
#ifdef GENERIC
template<typename Generic>
void print_typeid( const Generic& g ) {
std::cout << "(G) typeid: " << typeid(g).name() << std::endl;
}
#endif // GENERIC
int main( int argc, char *argv[] ) {
Foo foo; print_typeid(foo);
Bar bar; print_typeid(bar);
return 0;
}
测试用例
<强>1。仅定义 FOO
$ g++ -DFOO main.cpp -o foo && ./foo
输出:
(F) typeid: 3Foo
(F) typeid: 3Foo
这对我来说很有意义,因为对象 foo
和 bar
可能是
作为 const Foo&
传递并且因为没有编译时向下转换,
bar
必须被标识为具有 Foo
类型。
<强>2。仅定义 GENERIC
$ g++ -DGENERIC main.cpp -o generic && ./generic
输出:
(G) typeid: 3Foo
(G) typeid: 3Bar
这也很有意义,因为 foo
和 bar
都是左值,可以传递给采用通用常量引用的函数。这将打印每个对象的实际类型。
<强>3。定义 FOO 和 GENERIC
$ g++ -DFOO -DGENERIC main.cpp -o both && ./both
输出:
(F) typeid: 3Foo
(G) typeid: 3Bar
这个让我很困惑。已经确定这两个对象都可以传递给两个函数,我预计因为 const Foo&
是 bar
的更具体的兼容类型,所以我们会有相同的输出在案例 1 中。为什么会发生这种情况?
使用 gcc 7.2 和 clang 4 测试
最佳答案
This one confuses me. Having already established that both objects may be passed to both functions, I expected that because
const Foo&
is a more specific compatible type forbar
that we would have had the same output as in Case 1. Why does this happen?
但是 const Generic &
,当 Generic
推导为 Bar
时,对于一个 是一个更好的匹配(是精确匹配) >Bar
对象而不是 const Foo &
。
因此,当使用 Bar
对象调用时,首选和选择 print_typeid()
的模板版本。
相反,使用const Foo &
对象调用print_typeid()
,两个版本匹配,作为完全匹配,非模板版本优先于模板版本。
关于c++ - 函数模板参数推导和继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54962398/