重载函数中的歧义:如何解决

Ambiguity in overloaded function: how is it resolved?

本文关键字:何解决 解决 函数 歧义 重载      更新时间:2023-10-16

我重载了<<以两种不同的形式打印pair的内容(参见下面的代码)。第一种形式是特定于定义的pair类型的。第二个是template d,适用于任何一对。这两种都适合我这种类型的人。当两个原型都先于main的定义时,不管原型的顺序如何,都使用第一个(特定的)原型。只有当注释了第一个原型时,才会使用第二个原型。

为什么用这种方式解决歧义,决定使用哪个合适的函数?

#include <iostream>
#include <map>
using namespace std;
typedef pair<string, char> pair_t;
ostream& operator<<(ostream& os, const pair_t& p);   // First form, specific
template<class first_class, class second_class>
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p);   // Second form, generic
int main(void) {
        pair_t p2;
        p2 = make_pair("Fer", 'C');
        cout << p2 << endl;
        return 0;
}
ostream& operator<<(ostream& os, const pair_t& p)
{
    os << p.first << " obtained '" << p.second << "'";
    return os;
}
template<class first_class, class second_class>
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p)
{
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}

std::pair有一个重载的转换构造函数:

template< class U1, class U2 >
constexpr pair( const pair<U1, U2>& p );

你做了这个:

p2 = make_pair("Fer", 'C');

调用std::make_pair("Fer", 'C')返回一个类型为std::pair<const char[4], char>的对象,该对象可转换为std::pair<std::string, char>

传递给std::cout,将需要重载解析来实例化重载函数模板,创建一组函数专门化:

ostream& operator<<(ostream& os, const std::pair<std::string, char>& p)
ostream& operator<<(ostream& os, const std::pair<std::string, char>& p);    //compiler generated template specialization

可以选择的规则在这里捕获

对于每一对可行函数F1和F2,隐式转换从第i个形参到第i个实参的序列排序为确定哪个更好(除了第一个参数,隐式对象参数对静态成员函数没有影响排名)

如果F1的所有参数的隐式转换不差于隐式转换,则确定

F1是优于F2的函数F2

所有参数的转换
  1. 至少有一个F1的参数,其隐式转换优于对应的该参数的隐式转换 F2
  2. 。如果不是这样(仅在通过转换进行非类初始化的上下文中),则返回类型的标准转换序列F1到被初始化类型的转换顺序优于从F2
  3. 返回类型的标准转换顺序。
  4. 或者F1是非模板函数,而F2是模板专门化
  5. 或者F1F2都是模板专门化,而F1根据偏序规则更加专门化用于模板专门化