mercredi 1 août 2018

Understanding C++ choice of conversion operator

I've got an optional-like class (I can't use optional since it's in C++17). It contains a (possible) value along with a flag indicating if it's valid. I've got an explicit bool operator and a conversion operator to get the value out. The problem is, sometimes C++ will choose the bool operator in an explicitly bool context (an if statement), and other times it won't. Can anyone help me understand this behavior:

#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;
    }
}   

Aucun commentaire:

Enregistrer un commentaire