为什么调用带有转换构造函数的重载函数是不明确的?

问题描述 投票:0回答:2

这是如何避免从“double”到“int”的隐式转换?的后续问题。假设我有以下代码:

template <class T>
struct wrapper {
    wrapper(const T&);
};

void f(wrapper<int>);

void f(wrapper<double>);

int main () {
    f(1); // error: ambiguous call to overloaded function
}

参见编译器浏览器中的实时示例;请注意,所有主要编译器的行为都是相同的

怎么

f(1)
有歧义?有两种转换顺序:

  • 1
    ->
    const int&
    通过限定转换和引用绑定 ->
    wrapper<int>
    通过转换构造函数
  • 1
    ->
    const double&
    通过浮点转换、临时物化、限定转换和引用绑定 ->
    wrapper<double>
    通过转换构造函数

第一个转换序列看起来更好,那么为什么第一个重载没有获胜呢?

c++ language-lawyer overload-resolution
2个回答
3
投票

整个隐式转换序列由用户定义的转换序列组成:

格式良好的隐式转换序列是以下形式之一:

- [over.best.ics.general] p3

用户定义的转换序列由初始标准转换序列、用户定义的转换和第二个标准转换序列组成。

- [over.ics.user] p1

标准转换顺序

int -> const int&
int -> const double&
好,但是,没有考虑这一点。用户定义的转换序列
int -> wrapper<int>
int -> wrapper<double>
均按 [over.ics.rank] p2 排名,用户定义的转换序列之间的唯一区别在 [over.ics.rank] p3.3 仅适用于 second 标准转换。

与直觉相反:

    如果
  • wrapper<int> -> int -> const int&
     具有 
    wrapper<double> -> double -> const int&
     转换功能,
    转换
    wrapper<T>
    会比
    operator T
    更好。
  • 但是,转换
    int -> const int& -> wrapper<int>
    int -> const double& -> wrapper<double>
    的排名相同。

-3
投票

这有效:

template <class T>
struct wrapper {
  wrapper(const T&);
};

void f(wrapper<int>);

void f(wrapper<double>);

int main () {
   f(wrapper<double>(1.0));
   f(wrapper<int>(1));
}
© www.soinside.com 2019 - 2024. All rights reserved.