在同一个类中具有第二个隐式运算符的显式转换运算符的危险

时间:2019-02-04 20:21:44

标签: c++ c++11

我发现自己很想将两个转换运算符放在一个类中。通常我会像瘟疫一样避免这种情况。但是,使用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年代黑暗的年代烧毁了操作员。

所以我的问题:

这真的像看起来一样安全吗? 我是否缺少一些明显的情况,其中编译器会抱怨转换不明确甚至更糟,当我想要另一个操作员时,默默地呼叫一个操作员吗?

(要明确:我不是在问这个问题的必要性,也不是在它的可读性上。我只是在问我不想发生的编译时歧义或转换的危险。我需要巩固显式的概念。转换运算符在我的脑海。)

0 个答案:

没有答案