您可以在David Vandevoorde和Nicolai Josuttis所着的“C ++模板完整指南”一书的附录B中找到以下内容。
B.2简化过载分辨率
鉴于这第一个原则,我们留下了具体说明 给定的参数匹配一个可行的相应参数 候选人。作为第一个近似值,我们可以对可能的匹配进行排名 如下(从最佳到最差):
- 完美搭配。参数具有表达式的类型,或者它具有对表达式类型的引用的类型(可能 添加了const和/或volatile限定符)。
- 与次要调整匹配。这包括,例如,数组变量衰减到指向其第一个元素的指针,或者 添加const以将类型为int **的参数与参数相匹配 输入int const * const *。
- 与促销相匹配。促销是一种隐式转换,包括小整数类型的转换(如bool, char,short,有时是枚举)int,unsigned int,long或 unsigned long,以及float到double的转换。
- 仅与标准转化匹配。这包括任何类型的标准转换(例如int到float)但不包括隐式转换 调用转换运算符或转换构造函数。
- 与用户定义的转化匹配。这允许任何类型的隐式转换。
- 与省略号匹配。省略号参数几乎可以匹配任何类型(但非POD类类型会导致未定义的行为)。
几页后,本书展示了以下示例和文本(强调我的):
class BadString {
public:
BadString(char const*);
...
// character access through subscripting:
char& operator[] (size_t); // (1)
char const& operator[] (size_t) const;
// implicit conversion to null-terminated byte string:
operator char* (); // (2)
operator char const* ();
...
};
int main()
{
BadString str("correkt");
str[5] = 'c'; // possibly an overload resolution ambiguity!
}
起初,表达式str [5]似乎没有任何含糊之处。该 (1)的下标运算符似乎是完美的匹配。但是,确实如此 不太完美,因为参数5的类型为int,而且 operator需要一个无符号整数类型(size_t和std :: size_t 通常有unsigned int或unsigned long类型,但从不输入int)。 然而,简单的标准整数转换使得(1)容易生存。 但是,还有另一个可行的候选者:内置下标 运营商。实际上,如果我们将隐式转换运算符应用于str (这是隐式成员函数参数),我们获得一个指针 类型,现在内置的下标运算符适用。这个内置 operator接受类型为ptrdiff_t的参数,该参数在许多平台上都有 等价于int,因此是参数的完美匹配 5. 因此,即使内置的下标运算符与隐含参数的匹配不佳(通过用户定义的转换),它也是更好的 比(1)中定义的运算符匹配实际的下标!因此 潜在的歧义。
答案 0 :(得分:0)
请注意,第一个列表是 Simplified Overload Resolution。
要删除int
是否与ptrdiff_t
相同的“可能”和“潜在”,让我们更改一行:
str[(ptrdiff_t)5] = 'c'; // definitely an overload resolution ambiguity!
现在我从g++
收到的消息是:
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
和--pedantic-errors
会将此警告提升为错误。
因此,如果不深入标准,这会告诉您简化列表只是故事的一部分。该列表告诉您从A到B的几个可能的路线中哪一个更喜欢,但它不会告诉您是否更喜欢从A到B从C到D的旅行。
你可以在这里更明显地看到相同的现象(以及相同的g ++消息):
struct S {
explicit S(int) {}
operator int() { return 0; }
};
void foo(const S&, long) { }
void foo(int, int) { }
int main() {
S s(0);
foo(s, 1);
}
再次调用foo
是不明确的,因为当我们选择隐式转换哪个参数以选择重载时,规则不说,“选择更轻量级的转换,并转换需要转换的参数“。
现在你要问我标准的引用,但是我会用我需要打干草的事实作为不查找的借口; - )
总之,不这里“用户定义的转换比标准整数转换更好”。但是在这种情况下,标准定义的两个可能的重载同样好,因此调用是模糊的。
答案 1 :(得分:0)
str.operator[](size_t(5));
以明确的方式编写代码,你不需要为这些东西烦恼:) 事情还有很多。