繁体   English   中英

函数模板 - 当使用相同类型调用时,编译器选择具有不同参数类型的函数

[英]Function templates - compiler choosing function with different parameter types when calling with the same type

我正在玩功能模板,我偶然发现了一个奇怪的互动。

template<class T1, class T2>
void foo(T1, T1);

template<class T1, class T2>
void foo(T1, T2);

//main
foo(1,1)

这调用foo(T1,T2),我不明白为什么。 那会怎么样? 这些函数是否相互重载,为什么编译器会选择具有不同参数类型的函数?

Henri Menke的帖子的第一部分解释了这种特殊的互动


在经历了一些混乱后,我发现了一些更奇怪的东西

#include <iostream>

template<class T1, class T2>
void foo(T1 a, T1 b)
{
    std::cout << "same\n";
}

template<class T1, class T2>
void foo(T1 a, T2 b)
{
    std::cout << "different\n";
}

int main()
{
    foo(1, 1);
    foo<int, int>(1, 1);
}

在这段代码中我得到了一个结果

different
different

但在评论出第一个电话之后

int main()
{
    //foo(1, 1);
    foo<int, int>(1, 1);
}

结果是

same

我正在使用VS2015,如果我在Ideone中写同样的东西( 比如这里 ),第一个的结果是

different
same

有人能够解释发生了什么(或不发生了什么)?


顺便说一句,我得出的结论是调用foo<int, int>(1, 1); 应该是模棱两可的。 两个功能模板都具有相同的签名,并且来自同一模板。 那是另一回事,他们为什么不碰撞呢?

通过简单地删除第二个模板,即拥有类似的源文件,很容易看出为什么会失败

template<class T1, class T2>
void foo(T1, T1);

int main()
{
  foo(1,1);
}

这在Clang中失败了

test.cpp:6:3: error: no matching function for call to 'foo'
  foo(1,1);
  ^~~
test.cpp:2:6: note: candidate template ignored: couldn't infer template argument
      'T2'
void foo(T1, T1);
     ^
1 error generated.

编译器无法推导出第二个模板参数T2


如果从第一个模板中删除多余的T2并使用此类源文件

template<class T1>
void foo(T1, T1);

template<class T1, class T2>
void foo(T1, T2);

int main()
{
  foo(1,1);
}

编译器将始终选择第一个选项(如果T1T2当然是相同的),因为它更专业。

另一种选择是给T2一个默认值。 然后第一个变体也可以从foo(1,1)实例化。

template<class T1, class T2 = void>
void foo(T1, T1);

另一个有趣的事情是:

#include <iostream>

template<class T1, class T2>
void foo(T1, T1)
{ std::cout << "First choice!\n"; }

template<class T1, class T2>
void foo(T1, T2)
{ std::cout << "Second choice!\n"; }

int main()
{
  foo<int,int>(1,1);
}

这将在运行时输出:

First choice!

我不完全确定,但我相信这是因为在演绎的情况下(即使这里没有执行),对于第一个变体,编译器必须只推导出一种类型而不是两种类型,这使得它更多专业选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM