/* * compare.hpp * * This file is part of Algorithms library toolkit. * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz) * Algorithms library toolkit is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * Algorithms library toolkit is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>. * * Created on: Apr 1, 2013 * Author: Jan Travnicek */ #ifndef __COMPARE_HPP_ #define __COMPARE_HPP_ #include <utility> namespace ext { class CompareOperatorsBase { }; template < class T > class CompareOperators : public CompareOperatorsBase { public: /** * Compares this object with other for inequality. * * \returns true if this and other objects are not equal, false othervise */ bool operator !=( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) != 0; } /** * Compares this object with other for equality. * * \returns true if this and other objects are equal, false othervise */ bool operator ==( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) == 0; } /** * Determines whether this object is strictly smaller in relation to the other object. * * \returns true if this object is strictly smaller than other object are not equal, false othervise */ bool operator <( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) < 0; } /** * Determines whether this object is smaller or equal in relation to the other object. * * \returns true if this object is smaller or equal than other object are not equal, false othervise */ bool operator <=( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) <= 0; } /** * Determines whether this object is strictly bigger in relation to the other object. * * \returns true if this object is strictly bigger than other object are not equal, false othervise */ bool operator >( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) > 0; } /** * Determines whether this object is bigger or equal in relation to the other object. * * \returns true if this object is bigger or equal than other object are not equal, false othervise */ bool operator >=( const T & other ) const { return static_cast < const T & > ( * this ).compare ( other ) >= 0; } }; /** * \brief * Predefinition of the compare structure implementing the three-way comparison * * \tparam T the type of compared value * \tparam Enable the place for enable_if construct if needed */ template < typename T, typename Enable = void > struct compare; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for bools */ template < > struct compare < bool > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( bool first, bool second ) const { return static_cast < int > ( first ) - static_cast < int > ( second ); } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for unsigned chars */ template < > struct compare < unsigned char > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( unsigned char first, unsigned char second ) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for signed chars */ template < > struct compare < signed char > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( signed char first, signed char second ) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for chars */ template < > struct compare < char > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( char first, char second ) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for unsigned shorts */ template < > struct compare < unsigned short > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( unsigned short first, unsigned short second ) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for signed shorts */ template < > struct compare < signed short > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator()(signed short first, signed short second) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for unsigned ints */ template < > struct compare < unsigned int > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator()(unsigned int first, unsigned int second) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for signed ints */ template < > struct compare < signed int > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator()(signed int first, signed int second) const { return first - second; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for unsigned longs */ template < > struct compare < unsigned long > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( unsigned long first, unsigned long second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for signed longs */ template < > struct compare < signed long > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( signed long first, signed long second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for unsigned long longs */ template < > struct compare < unsigned long long > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( unsigned long long first, unsigned long long second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for signed long longs */ template < > struct compare < signed long long > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( signed long long first, signed long long second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for floats */ template < > struct compare < float > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( float first, float second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for doubles */ template < > struct compare < double > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( double first, double second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for long doubles */ template < > struct compare < long double > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( long double first, long double second ) const { if ( first < second ) return -1; else if ( first > second ) return 1; else return 0; } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for pointers * * \tparam T the type of compared pointer */ template < class T > struct compare < T * > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( T * const first, T * const second ) const { static compare < typename std::decay < T >::type > comp; return comp ( * first, * second ); } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for lvalue references * * \tparam T the type of compared reference */ template < class T > struct compare < T & > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( const T & first, const T & second ) const { static compare < typename std::decay < T >::type > comp; return comp ( first, second ); } }; /** * \brief * Specialisation of the compare structure implementing the three-way comparison for rvalue references * * \tparam T the type of compared reference */ template < class T > struct compare < T && > { /** * \brief * Implementation of the three-way comparison * * \param first the left operand of the comparison * \param second the right operand of the comparison * * \return negative value of left < right, positive value if left > right, zero if left == right */ int operator ( ) ( const T & first, const T & second ) const { static compare < typename std::decay < T >::type > comp; return comp ( first, second ); } }; /** * Helper for comparing everything that inherits from CommonBaseBase. * * \tparam T the type to compare */ template < class T > struct compare < T, typename std::enable_if < std::is_base_of < CompareOperatorsBase, typename std::decay < T >::type >::value >::type > { /** * Compare operator that determines relation between first and second object. * * \returns value < 0 if first < second * value == 0 if first == second * value > 0 if first > second */ int operator()(const T& first, const T& second) const { return first.compare(second); } }; } /* namespace ext */ #endif /* __COMPARE_HPP_ */