这是一个更复杂的问题,如果参数是一个重载函数,重载决策是如何工作的?
下面的代码编译没有任何问题:
void foo() {}
void foo(int) {}
void foo(double) {}
void foo(int, double) {}
// Uncommenting below line break compilation
//template<class T> void foo(T) {}
template<class X, class Y> void bar(void (*f)(X, Y))
{
f(X(), Y());
}
int main()
{
bar(foo);
}
Run Code Online (Sandbox Code Playgroud)
模板参数推导似乎不是一项具有挑战性的任务 - 只有一个函数foo()接受两个参数.但是,取消注释模板重载foo()(仍然只有一个参数)会破坏编译,没有明显的原因.使用gcc 5.x/6.x和clang 3.9编译失败.
可以通过重载决策/模板参数推导的规则来解释它还是应该被认为是那些编译器中的缺陷?
大多数IO流操纵器都是具有以下签名的常规函数:
std::ios_base& func( std::ios_base& str );
Run Code Online (Sandbox Code Playgroud)
但是,一些操纵器(包括最常用的操纵器 - std::endl和std::flush)是以下形式的模板:
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& func(std::basic_ostream<CharT, Traits>& os);
Run Code Online (Sandbox Code Playgroud)
然后,如果std::cout << std::endl;以下示例失败,如何编译成功:
$ cat main.cpp
#include <iostream>
int main()
{
auto myendl = std::endl;
std::cout << myendl;
}
$ g++ -std=c++11 main.cpp -o main
main.cpp: In function ‘int main()’:
main.cpp:5:24: error: unable to deduce ‘auto’ from ‘std::endl’
auto myendl = std::endl;
^
Run Code Online (Sandbox Code Playgroud)
很明显,上下文(in std::cout << std::endl;)有助于编译器消除对引用的歧义std::endl.但是,管理该程序的规则是什么?对于重载分辨率来说,这似乎是一个真正的挑战,它必须同时回答两个问题:
std::endl<CharT, Traits>() …