Skip to content
Snippets Groups Projects
Commit 9a8c6b5f authored by Jan Trávníček's avatar Jan Trávníček Committed by Tomáš Pecka
Browse files

multiset extensions

parent ab4989bd
No related branches found
No related tags found
1 merge request!119Merge jt
Pipeline #58568 passed with warnings
#include <extensions/container/multiset.hpp>
/*
* multiset.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 __MULTI_SET_H_
#define __MULTI_SET_H_
#include <set>
#include <ostream>
#include <sstream>
#include <string>
#include <extensions/compare.hpp>
#include <extensions/range.hpp>
namespace ext {
/**
* Class extending the multiset class from the standard library. Original reason is to allow printing of the container with overloaded operator <<.
*
* The class mimics the behavior of the multiset from the standatd library.
*
* \tparam T the type of keys inside the multiset
* \tparam Cmp the comparator type used to order keys
* \tparam Alloc the allocator of values of type T
*/
template < typename T, typename Cmp = std::less < >, typename Alloc = std::allocator < T > >
class multiset : public std::multiset < T, Cmp, Alloc > {
public:
/**
* Inherit constructors of the standard multiset
*/
using std::multiset < T, Cmp, Alloc >::multiset; // NOLINT(modernize-use-equals-default)
/**
* Inherit operator = of the standard multiset
*/
using std::multiset < T, Cmp, Alloc >::operator =;
#ifndef __clang__
/**
* Default constructor needed by g++ since it is not inherited
*/
multiset ( ) = default;
/**
* Copy constructor needed by g++ since it is not inherited
*/
multiset ( const multiset & other ) = default;
/**
* Move constructor needed by g++ since it is not inherited
*/
multiset ( multiset && other ) = default;
/**
* Copy operator = needed by g++ since it is not inherited
*/
multiset & operator = ( multiset && other ) = default;
/**
* Move operator = needed by g++ since it is not inherited
*/
multiset & operator = ( const multiset & other ) = default;
#endif
/**
* Constructor from range of values.
*
* \tparam Iterator the type of range iterator
*
* \param range the source range
*/
template < class Iterator >
explicit multiset ( const ext::iterator_range < Iterator > & range ) : multiset ( range.begin ( ), range.end ( ) ) {
}
/**
* \brief
* Inherited behavior of begin for non-const instance.
*
* \return iterator the first element of multiset
*/
auto begin ( ) & {
return std::multiset < T, Cmp, Alloc >::begin ( );
}
/**
* \brief
* Inherited behavior of begin for const instance.
*
* \return const_iterator the first element of multiset
*/
auto begin ( ) const & {
return std::multiset < T, Cmp, Alloc >::begin ( );
}
/**
* \brief
* New variant of begin for rvalues.
*
* \return move_iterator the first element of multiset
*/
auto begin ( ) && {
return make_set_move_iterator ( this->begin ( ) );
}
/**
* \brief
* Inherited behavior of end for non-const instance.
*
* \return iterator to one after the last element of multiset
*/
auto end ( ) & {
return std::multiset < T, Cmp, Alloc >::end ( );
}
/**
* \brief
* Inherited behavior of end for const instance.
*
* \return const_iterator to one after the last element of multiset
*/
auto end ( ) const & {
return std::multiset < T, Cmp, Alloc >::end ( );
}
/**
* \brief
* New variant of end for rvalues.
*
* \return move_iterator to one after the last element of multiset
*/
auto end ( ) && {
return make_set_move_iterator ( this->end ( ) );
}
/**
* \brief
* Make range of non-const begin to end iterators.
*
* \return full range over container values
*/
auto range ( ) & {
auto endIter = end ( );
auto beginIter = begin ( );
return ext::iterator_range < decltype ( endIter ) > ( beginIter, endIter );
}
/**
* \brief
* Make range of non-const begin to end iterators.
*
* \return full range over container values
*/
auto range ( ) const & {
auto endIter = end ( );
auto beginIter = begin ( );
return ext::iterator_range < decltype ( endIter ) > ( beginIter, endIter );
}
/**
* \brief
* Make range of move begin to end iterators.
*
* \return full range over container values
*/
auto range ( ) && {
auto endIter = std::move ( * this ).end ( );
auto beginIter = std::move ( * this ).begin ( );
return ext::iterator_range < decltype ( endIter ) > ( beginIter, endIter );
}
/**
* \brief
* Make range of elements with key equal to the @p key.
*
* \tparam K the key used in the query
*
* \param key the value used in the query
*
* \return selected range of elements
*/
template < class K >
auto equal_range ( K && key ) const & {
auto res = std::multiset < T, Cmp, Alloc >::equal_range ( std::forward < K > ( key ) );
return ext::iterator_range < decltype ( res.first ) > ( res.first, res.second );
}
/**
* \brief
* Make range of elements with key equal to the @p key.
*
* \tparam K the key used in the query
*
* \param key the value used in the query
*
* \return selected range of elements
*/
template < class K >
auto equal_range ( K && key ) & {
auto res = std::multiset < T, Cmp, Alloc >::equal_range ( std::forward < K > ( key ) );
return ext::iterator_range < decltype ( res.first ) > ( res.first, res.second );
}
/**
* \brief
* Make range of elements with key equal to the @p key.
*
* \tparam K the key used in the query
*
* \param key the value used in the query
*
* \return selected range of elements
*/
template < class K >
auto equal_range ( K && key ) && {
auto res = std::multiset < T, Cmp, Alloc >::equal_range ( std::forward < K > ( key ) );
return ext::make_iterator_range ( make_set_move_iterator < T > ( res.first ), make_set_move_iterator < T > ( res.second ) );
}
/**
* \brief
* Test whether the multiset contains a given key
*
* \param key the tested key
*
* \return true if the multiset contains the key, false otherwise
*/
bool contains ( const T & key ) const { // TODO remove after switching C++20
return this->count ( key ) != 0U;
}
/**
* \brief
* Test whether the multiset contains a given key
*
* \tparam K the type of the key
*
* \param key the tested key
*
* \return true if the multiset contains the key, false otherwise
*/
template < class K >
bool contains ( const K & key ) const { // TODO remove after switching C++20
return this->count ( key ) != 0U;
}
};
/**
* \brief
* Operator to print the multiset to the output stream.
*
* \param out the output stream
* \param multiset the multiset to print
*
* \tparam T the type of keys inside the multiset
* \tparam R the type of values inside the multiset
* \tparam Ts ... remaining unimportant template parameters of the multiset
*
* \return the output stream from the \p out
*/
template< class T, class ... Ts >
std::ostream& operator<<(std::ostream& out, const ext::multiset<T, Ts ...>& list) {
out << "{";
bool first = true;
for(const T& item : list) {
if(!first) out << ", ";
first = false;
out << item;
}
out << "}";
return out;
}
/**
* \brief
* Specialisation of the compare structure implementing the three-way comparison.
*
* \tparam T the type of keys inside the multiset
* \tparam R the type of values inside the multiset
* \tparam Ts ... remaining unimportant template parameters of the multiset
*/
template<class T, class ... Ts>
struct compare < ext::multiset < T, Ts ... > > {
/**
* \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 ext::multiset<T, Ts ...>& first, const ext::multiset<T, Ts ...>& second) const {
if(first.size() < second.size()) return -1;
if(first.size() > second.size()) return 1;
static compare<typename std::decay < T >::type > comp;
for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
int res = comp(*iterF, *iterS);
if(res != 0) return res;
}
return 0;
}
};
/**
* \brief
* Overload of to_string function.
*
* \param value the multiset to be converted to string
*
* \tparam T the type of values inside the multiset
* \tparam Ts ... remaining unimportant template parameters of the multiset
*
* \return string representation
*/
template < class T, class ... Ts >
std::string to_string ( const ext::multiset < T, Ts ... > & value ) {
std::stringstream ss;
ss << value;
return ss.str();
}
/**
* \brief
* Implementation of union of two multisets.
*
* \tparam T the type of values stored in unioned multisets
*
* \param first the first multiset to union
* \param second the second multiset to union
*
* \return multiset representing union
*/
template < class T >
ext::multiset < T > operator +( const ext::multiset < T > & first, const ext::multiset < T > & second ) {
ext::multiset < T > res ( first );
res.insert ( second.begin ( ), second.end ( ) );
return res;
}
} /* namespace ext */
#endif /* __MULTI_SET_H_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment