WilliamKF
WilliamKF

Reputation: 43149

Can the equivalent of an operator bool cast be provided outside of a class definition somehow?

I have some templated C++-03 code that includes a snippet that I'd like to write something like this:

template <typeName optType>
std::string
example(optType &origVal)
{
  return bool(origVal) ? "enabled" : "disabled";
}

However, there is no optType::operator bool() defined for struct linger and I cannot add one as that struct is not mine. Therefore, for now, I have written it as this instead:

template <typename optType>
bool
castBool(const optType &value)
{
  return bool(value);
}

template <>
bool
castBool<struct linger>(const struct linger &value)
{
  return bool(value.l_onoff);
}

template <typeName optType>
std::string
example(optType &origVal)
{
  return castBool(origVal) ? "enabled" : "disabled";
}

But, I'm wondering if there is a more succinct way to do this? For example, I can define a static operator==() outside of a class, such as like this:

bool
operator==(const struct linger &lhs, const struct linger &rhs)
{
  return lhs.l_onoff == rhs.l_onoff && lhs.l_linger == rhs.l_linger;
}

So perhaps there is some syntax to tell the compiler how to promote a struct such as the struct linger here to a bool?

Upvotes: 3

Views: 598

Answers (2)

bartop
bartop

Reputation: 10315

As operator bool can be only a method, not a standalone function, I think one of solutions is generating derived class from the one you want to cast to bool and implement only your operator there. This will work unless the class we are talking about is final.

class Boolable : public optType{
public:
    using optType::optType;
    operator bool() const{
        //your code her
    }
};

Upvotes: 0

Barry
Barry

Reputation: 303097

You could provide some default version in a namespace:

namespace detail {
    template <typename T>
    bool to_bool(const T& val) { return static_cast<bool>(val); }
}

template <typename T>
bool conv_bool(const T& val) {
    using namespace detail;
    return to_bool(val);
}

And then with the magic of ADL, you can just provide a version of to_bool in the namespace of the class you want:

namespace whatever {
    struct linger { ... };

    bool to_bool(const linger& value) {
        return value.l_onoff;
    }
}

And then just use conv_bool everywhere:

template <typeName optType>
std::string
example(optType &origVal)
{
  return conv_bool(origVal) ? "enabled" : "disabled";
}

If you provided your own to_bool() function, that will get preferred. Otherwise, the default one will get called which will try to do operator bool or some equivalent. No having to deal with template issues.

Upvotes: 2

Related Questions