下面是一个 C++ 代码片段,演示了一个Foo
包装 的类std::optional<double>
,为double
和提供转换运算符std::optional<double>
。
#include <iostream>
#include <optional>
class Foo {
public:
operator double() const {
std::cout << "Foo::operator double()" << std::endl;
return {};
}
operator std::optional<double>() const {
std::cout << "Foo::operator std::optional<double>()" << std::endl;
return {};
}
};
int main() {
Foo foo;
std::optional<double> value;
// Outputs "Foo::operator double()"
value = foo;
}
令我惊讶的是,当将 的实例分配Foo
给 a 时std::optional<double>
,调用的是 的转换运算符double
,而不是 的转换运算符std::optional<double>
。
当我std::optional
用自己的自定义Optional
类替换时,如下所示,编译器选择了另一个转换运算符。
#include <iostream>
template<class T>
class Optional {
public:
T val;
Optional() = default;
Optional(T) {
std::cout << "Optional(T)" << std::endl;
}
Optional(Optional&&) noexcept {
std::cout << "Optional(Optional&&)" << std::endl;
}
Optional(const Optional<T>&) {
std::cout << "Optional(const Optional&)" << std::endl;
}
Optional& operator=(Optional&&) noexcept {
std::cout << "Optional::operator=(Optional&&)" << std::endl;
return *this;
}
operator const T& () const {
std::cout << "Optional::operator const T&()" << std::endl;
return val;
}
};
class Foo {
public:
operator double() const {
std::cout << "Foo::operator double()" << std::endl;
return {};
}
operator Optional<double>() const {
std::cout << "Foo::operator Optional<double>()" << std::endl;
return {};
}
};
int main() {
Foo foo;
Optional<double> value;
// Outputs
// Foo::operator Optional<double>()
// Optional::operator=(Optional&&)
value = foo;
}
为什么编译器在每种情况下都会选择不同的转换运算符?
以下是赋值运算符重载的 cppreference 列表。唯一直接匹配的是数字 4:
只有满足以下要求,它才会参与过载:
只要 U 为 Foo,所有要求都满足。选择重载后,只能
Foo::operator double() const
分配给 double 值optional<double>