我发现自己很想将两个转换运算符放在一个类中。通常我会像瘟疫一样避免这种情况。但是,使用C ++ 11和显式转换运算符,似乎我想要实现的既合理又安全。但是我需要进行健全性检查。
请考虑以下类别(“距离”),该类别旨在将距离值与其度量单位绑定在一起。
enum class Unit { None = 0, Meter = 1, Foot = 2, }; // None means INVALID
class Distance
{
Unit m_unit;
double m_value;
public:
Distance() : m_unit(Unit::None), m_value(0.f) {} // construct invalid
Distance(Unit u, double, v) : m_unit(u), m_value(v) {}
Unit unit() const { return m_unit; }
// Two functions that I would like to make into cast operators:
double value() const { return m_value; }
bool valid() const { return Unit::None != m_unit; }
// Cast operators I would LIKE to add and use. Implicitly cast to
// double but in "if()" scenarios, cast to bool to check validity
operator double() const { return m_value; }
explicit operator bool() { return valid(); }
};
由于距离对象(大多数情况下)被视为好像是一个双精度值,因此我考虑了添加隐式双精度强制转换(以上)。但是在某些情况下,距离可以视为“无效”,以Unit :: None的单位值表示。在那种情况下,我真的很喜欢添加显式布尔强制转换的想法。
最终目标是能够替换当前如下所示的代码:
void doSomething(bool b) {}
void doSomething(double d) {}
void DumpDistance(const Distance& dist)
{
if (dist.valid())
std::cout << dist.value() << std::endl;
doSomething(dist.valid()); // properly calls bool version
doSomething(dist.value()); // properly called double version
}
对此:
void DumpDistance(const Distance& dist)
{
if (dist) // treated as bool (good)
std::cout << dist << std::endl; // treated as double (good)
doSomething(dist); // calls double overload (good)
}
在我的测试中,显式布尔运算符似乎可以解决问题。但是我不确定。似乎正在调用所需的重载。但是我内在地讨厌在1990年代黑暗的年代烧毁了操作员。
所以我的问题:
这真的像看起来一样安全吗? 我是否缺少一些明显的情况,其中编译器会抱怨转换不明确甚至更糟,当我想要另一个操作员时,默默地呼叫一个操作员吗?
(要明确:我不是在问这个问题的必要性,也不是在它的可读性上。我只是在问我不想发生的编译时歧义或转换的危险。我需要巩固显式的概念。转换运算符在我的脑海。)