Можно ли каким-то образом обеспечить эквивалент приведения типа operator bool вне определения класса?

У меня есть шаблонный код C ++ - 03, который включает фрагмент, который я хотел бы написать примерно так:

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

Однако для struct linger не определено optType::operator bool(), и я не могу добавить его, поскольку этот struct не мой. Поэтому сейчас я написал это так:

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

Но мне интересно, есть ли более лаконичный способ сделать это? Например, я могу определить статический operator==() вне класса, например так:

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

Так что, возможно, есть какой-то синтаксис, чтобы сообщить компилятору, как преобразовать структуру, такую ​​как struct linger здесь, в bool?


person WilliamKF    schedule 12.07.2015    source источник
comment
operator bool() может быть реализован только как участник, а не как самостоятельный. Ваша существующая специализация шаблона - это решение.   -  person Remy Lebeau    schedule 12.07.2015


Ответы (2)


Вы можете указать версию по умолчанию в пространстве имен:

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

А затем с помощью волшебства ADL вы можете просто предоставить версию to_bool в пространстве имен нужного вам класса:

namespace whatever {
    struct linger { ... };

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

А затем просто используйте conv_bool везде:

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

Если вы предоставили свою собственную to_bool() функцию, она будет предпочтительнее. В противном случае будет вызван метод по умолчанию, который попытается выполнить operator bool или что-то подобное. Нет необходимости решать проблемы с шаблоном.

person Barry    schedule 12.07.2015

Поскольку operator bool может быть только методом, а не отдельной функцией, я думаю, что одно из решений создает производный класс из того, который вы хотите преобразовать в bool, и реализуйте там только свой оператор. Это будет работать, если только класс, о котором мы говорим, не final.

class Boolable : public optType{
public:
    using optType::optType;
    operator bool() const{
        //your code her
    }
};
person bartop    schedule 12.07.2015
comment
Я думаю, вы имеете в виду функцию-член ... она не обязательно должна быть virtual (как метод) - person Ben Voigt; 12.07.2015
comment
@BenVoigt AFAIK method == функция-член. stackoverflow.com/questions/8596461/ - person bartop; 12.07.2015
comment
Нет, они совсем не эквивалентны. Я видел два общих определения метода - диспетчеризация на основе объектов (динамического типа), которая включает только виртуальные функции-члены, и диспетчеризация на основе статического типа, которая вообще не обязательно должна быть членом. - person Ben Voigt; 13.07.2015