我有一个类似可选的类(我不能使用可选的,因为它在C 17中).它包含一个(可能的)值以及一个指示它是否有效的标志.我有一个显式的bool运算符和一个转换运算符来获取值.问题是,有时C会在
#include <algorithm>
#include <stdexcept>
template <typename T>
struct maybe {
maybe() : valid_(false) {}
maybe(T value) : valid_(true) { new (&value_) T(value); }
operator T&&() {
return std::move(value());
}
explicit operator bool() const {
return valid_;
}
T& value() {
if (!valid_) {
throw std::runtime_error("boom");
}
return value_;
}
private:
union {
T value_;
};
bool valid_;
};
int main() {
// fine, uses operator bool()
maybe<std::pair<int,int>> m0;
if (m0) {
std::pair<int,int> p = m0;
(void)p;
}
// throws error, uses operator T&&()
maybe<double> m1;
if (m1) {
double p = m1;
(void)p;
}
}
每当你写:
if (x)
这相当于写了:
bool __flag(x); if (__flag)
这称为bool的上下文转换(请注意,它是直接初始化,因此显式转换函数是候选者).
当我们对m0的构造进行重载解析时,只有一个有效的候选者:显式运算符bool()const.
但是当我们对m1的构造进行重载解析时,有两个:显式运算符bool()const和operator double&&(),因为double可以转换为bool.后者是更好的匹配,因为bool转换函数具有额外的const限定,即使我们必须进行额外的双重转换.因此,它赢了.
只需从您的界面中删除运算符T&&(),因为它对此类型没有多大意义.
