logical.hpp 6.83 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
/*
 *          Copyright Andrey Semashev 2007 - 2014.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   logical.hpp
 * \author Andrey Semashev
 * \date   30.03.2008
 *
 * This header contains logical predicates for value comparison, analogous to \c std::less, \c std::greater
 * and others. The main difference from the standard equivalents is that the predicates defined in this
 * header are not templates and therefore do not require a fixed argument type. Furthermore, both arguments
 * may have different types, in which case the comparison is performed without type conversion.
 *
 * \note In case if arguments are integral, the conversion is performed according to the standard C++ rules
 *       in order to avoid warnings from the compiler.
 */

#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_

#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace aux {

//! The trait creates a common integral type suitable for comparison. This is mostly to silence compiler warnings like 'signed/unsigned mismatch'.
template< typename T, typename U, unsigned int TSizeV = sizeof(T), unsigned int USizeV = sizeof(U), bool TSmallerThanU = (sizeof(T) < sizeof(U)) >
struct make_common_integral_type
{
    typedef T type;
};

//! Specialization for case when \c T is smaller than \c U
template< typename T, typename U, unsigned int TSizeV, unsigned int USizeV >
struct make_common_integral_type< T, U, TSizeV, USizeV, true >
{
    typedef U type;
};

//! Specialization for the case when both types have the same size
template< typename T, typename U, unsigned int SizeV >
struct make_common_integral_type< T, U, SizeV, SizeV, false > :
    public mpl::if_<
        is_unsigned< T >,
        T,
        U
    >
{
};

} // namespace aux

//! Equality predicate
struct equal_to
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left == right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) == static_cast< common_integral_type >(right);
    }
};

//! Inequality predicate
struct not_equal_to
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left != right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) != static_cast< common_integral_type >(right);
    }
};

//! Less predicate
struct less
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left < right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) < static_cast< common_integral_type >(right);
    }
};

//! Greater predicate
struct greater
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left > right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) > static_cast< common_integral_type >(right);
    }
};

//! Less or equal predicate
struct less_equal
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left <= right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) <= static_cast< common_integral_type >(right);
    }
};

//! Greater or equal predicate
struct greater_equal
{
    typedef bool result_type;

    template< typename T, typename U >
    bool operator() (T const& left, U const& right) const
    {
        return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
    }

private:
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::false_ const&)
    {
        return (left >= right);
    }
    template< typename T, typename U >
    static bool op(T const& left, U const& right, mpl::true_ const&)
    {
        typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
        return static_cast< common_integral_type >(left) >= static_cast< common_integral_type >(right);
    }
};

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_