c++ - 函数模板参数推导和继承

标签 c++ templates inheritance template-argument-deduction type-deduction

我以为会调用具有最具体的匹配参数类型的函数重载,但我似乎不理解模板和继承类型组合时类型推导的一个方面。

例子:

#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

这对我来说很有意义,因为对象 foobar 可能是 作为 const Foo& 传递并且因为没有编译时向下转换, bar 必须被标识为具有 Foo 类型。

<强>2。仅定义 GENERIC

$ g++ -DGENERIC main.cpp -o generic && ./generic

输出:

(G) typeid: 3Foo
(G) typeid: 3Bar

这也很有意义,因为 foobar 都是左值,可以传递给采用通用常量引用的函数。这将打印每个对象的实际类型。

<强>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 for bar 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/

相关文章:

c++ - 检查两个对象组合的空值的最佳方法

python - 让一个函数设置一个全局变量

c++ - Typedef是在C++编译时解析的吗?

wpf - 为什么要在xaml,WPF的样式中定义模板?

c++ - 使 C++ 模拟类同时使用 2D 和 3D vector

c++ - 试图在数组中获取一个两倍于平均值的数字

c++ - C++ 编译器错误 "looks like a function definition, but there is no parameter list;"是什么意思?

c# - ASP.NET EF 从未映射的类中删除鉴别器列

python - 使用就地切片扩展列表类

java - 如何在调用方法时绕过java中的继承