Опасности явного оператора преобразования со вторым неявным оператором в том же классе - PullRequest
0 голосов
/ 04 февраля 2019

Я нахожусь в ситуации, когда у меня возникает соблазн поместить два оператора преобразования в один класс.Обычно я бы избегал этого, как чума.Но с 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(); }
};

Поскольку объект Distance предназначен для обработки, как если бы он был двойным значением (большую часть времени), я подумал о добавлении неявного двойного приведения (выше).Но в определенных контекстах расстояние может считаться недействительным, представленное значением единицы измерения 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)
}

В моем тестировании кажется, что явный оператор bool добивается цели.Но я не уверен.Похоже, требуемые перегрузки вызываются.Но у меня есть встроенное отвращение к операторам кастинга, сгоревшим во мне в темные старые времена 1990-х годов.

Поэтому мой вопрос:

Это действительно так же безопаснокак кажется? Есть ли какой-то очевидный случай, в котором я пропускаю, когда компилятор жаловался бы на неоднозначное преобразование или, что еще хуже, беззвучно вызывает один оператор, когда мне нужен другой? *

(Длябыть ясным: я не спрашиваю ни о необходимости этого, ни о его удобочитаемости. Только об опасностях двусмысленностей или преобразований во время компиляции, которых я не хочу делать. Мне нужно закрепить концепцию явных операторов преобразования в моей голове.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...