删除转换运算符
Deleting conversion operators
有没有办法禁用转换运算符?将它们标记为“=删除”会搞乱其他事情。
考虑以下代码:
class Foo
{
public:
Foo() :mValue(0) {}
~Foo() = default;
Foo(int64_t v) { mValue = v; }
Foo(const Foo& src) = default;
bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }
/* after commenting these lines the code will compile */
operator int() const = delete;
operator int64_t() const = delete;
private:
int64_t mValue;
};
int main()
{
Foo foo1(5);
Foo foo2(10);
bool b1 = (foo1 == foo2);
bool b2 = (foo1 == 5);
}
这不会编译,因为 gcc 抱怨 == 运算符不明确:
test.cc: In function ‘int main()’:
test.cc:25:21: error: ambiguous overload for ‘operator==’ (operand types are ‘Foo’ and ‘int’)
bool b2 = (foo1 == 5);
^
test.cc:25:21: note: candidates are:
test.cc:25:21: note: operator==(int, int) <built-in>
test.cc:25:21: note: operator==(int64_t {aka long int}, int) <built-in>
test.cc:10:10: note: bool Foo::operator==(const Foo&)
bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }
^
但是,在注释转换运算符之后,代码将编译并且 运行 很好。
第一个问题是:为什么删除的转换运算符会为==运算符造成歧义?我认为他们应该禁用隐式 Foo -> int 转换,但它们似乎会影响 int -> Foo 转换,这对我来说听起来不合逻辑。
第二个:有没有办法标记转换运算符被删除?是的,通过不声明它们 - 但我正在寻找一种方式,将来任何人都会看到这些转换被设计禁用。
Any use of a deleted function is ill-formed (the program will not
compile).
If the function is overloaded, overload resolution takes place first,
and the program is only ill-formed if the deleted function was
selected.
在你的情况下,程序无法select转换,因为你有 3 个变体
int -> Foo
Foo -> int
Foo -> int64
第二个问题:
你可以保持原样,但始终对 int
使用显式转换
bool b2 = (foo1 == Foo(5));
我认为问题的关键在于:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
...
A deleted function is implicitly an inline function ([dcl.inline]).
If C contains a declaration of the name f, the declaration set
contains every declaration of f declared in C that satisfies the
requirements of the language construct in which the lookup occurs.
即使你 delete
函数,你仍然声明它。并且声明的函数将参与重载决议。只有当它是已解析的重载时,编译器才会检查它是否被删除。
在您的情况下,当这些函数声明存在时,存在明显的歧义。
有没有办法禁用转换运算符?将它们标记为“=删除”会搞乱其他事情。
考虑以下代码:
class Foo
{
public:
Foo() :mValue(0) {}
~Foo() = default;
Foo(int64_t v) { mValue = v; }
Foo(const Foo& src) = default;
bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }
/* after commenting these lines the code will compile */
operator int() const = delete;
operator int64_t() const = delete;
private:
int64_t mValue;
};
int main()
{
Foo foo1(5);
Foo foo2(10);
bool b1 = (foo1 == foo2);
bool b2 = (foo1 == 5);
}
这不会编译,因为 gcc 抱怨 == 运算符不明确:
test.cc: In function ‘int main()’:
test.cc:25:21: error: ambiguous overload for ‘operator==’ (operand types are ‘Foo’ and ‘int’)
bool b2 = (foo1 == 5);
^
test.cc:25:21: note: candidates are:
test.cc:25:21: note: operator==(int, int) <built-in>
test.cc:25:21: note: operator==(int64_t {aka long int}, int) <built-in>
test.cc:10:10: note: bool Foo::operator==(const Foo&)
bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }
^
但是,在注释转换运算符之后,代码将编译并且 运行 很好。
第一个问题是:为什么删除的转换运算符会为==运算符造成歧义?我认为他们应该禁用隐式 Foo -> int 转换,但它们似乎会影响 int -> Foo 转换,这对我来说听起来不合逻辑。
第二个:有没有办法标记转换运算符被删除?是的,通过不声明它们 - 但我正在寻找一种方式,将来任何人都会看到这些转换被设计禁用。
Any use of a deleted function is ill-formed (the program will not compile).
If the function is overloaded, overload resolution takes place first, and the program is only ill-formed if the deleted function was selected.
在你的情况下,程序无法select转换,因为你有 3 个变体
int -> Foo
Foo -> int
Foo -> int64
第二个问题: 你可以保持原样,但始终对 int
使用显式转换bool b2 = (foo1 == Foo(5));
我认为问题的关键在于:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
...
A deleted function is implicitly an inline function ([dcl.inline]).
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in C that satisfies the requirements of the language construct in which the lookup occurs.
即使你 delete
函数,你仍然声明它。并且声明的函数将参与重载决议。只有当它是已解析的重载时,编译器才会检查它是否被删除。
在您的情况下,当这些函数声明存在时,存在明显的歧义。