It's probably a good idea to use a bool wrapper type for function
results, and in general,
and equally true, it's probably impossible to convince more than maybe
one or two programmers in the world to do that, because C and C++
programmers are as a whole extremely conservative.
A wrapper can go like this:
template< class T >
static constexpr bool is_bool_ = std::is_same_v<T, bool>;
template< class Truth_class >
struct Truth_values_
{
static const Truth_class yes;
static const Truth_class no;
};
class Truth:
public Truth_values_<Truth>
{
bool m_value;
public:
/// \brief Implicit conversion to `bool` (only).
///
/// Implicit conversion to `bool` because that's needed for
template args.
/// Restricted via SFINAE because overload resolution, want
predictability.
template<
class Result,
class = Enable_if_<is_bool_<Result>>
>
constexpr operator Result() const noexcept { return m_value; }
/// \brief Construction from `bool` (only).
///
/// Construction SFINAE-restricted to `bool` argument.
template<
class Arg,
class = Enable_if_<is_bool_<Arg>>
>
constexpr Truth( const Arg value ) noexcept: m_value( value ) {}
};
template< class Truth_class >
const Truth_class Truth_values_<Truth_class>::yes = true;
template< class Truth_class >
const Truth_class Truth_values_<Truth_class>::no = false;
constexpr inline auto is_true( const Truth value )
-> Truth
{ return value; }
constexpr inline auto is_false( const Truth value )
-> Truth
{ return not value; }
constexpr inline auto operator+( const Truth value )
-> int
{ return 0 + !!value; }
constexpr inline auto operator!=( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs != !!rhs; }
constexpr inline auto operator<=( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs <= !!rhs; }
constexpr inline auto operator<( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs < !!rhs; }
constexpr inline auto operator==( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs == !!rhs; }
constexpr inline auto operator>=( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs >= !!rhs; }
constexpr inline auto operator>( const Truth lhs, const Truth rhs )
-> bool
{ return !!lhs > !!rhs; }
<url:
https://github.com/alf-p-steinbach/cppx-core-language/blob/master/source/cppx-core-language/types/Truth.hpp>
---
There is a question here also:
is there a possibly better way to declare the `Truth::yes` and
`Truth::no` constants?
The above “templated constant” trick feels Just Wrong™, but it was
evidently the best I could come up with at the time when I wrote that.
- Alf