erase

概要:削除

remove_erase

概要:

要素の削除(std::remove()をしただけでは後ろにゴミが残るので、eraseで削除する)

手段:
  • リストの場合、 remove(value) remove_if(predicate) メソッドで削除する
    List.remove(value);
    List.remove_if(predicate);
    • forward_list
    • list

  • 連想コンテナの場合、 erase(value) メソッドで削除する
    Associative.erase(value);
    • set
    • multiset
    • map
    • multimap
    • unordered_set
    • unordered_multiset
    • unordered_map
    • unordered_multimap

  • 連続メモリコンテナの場合、 erase(begin, end) メソッドで削除する
    Sequence.erase(std::remove(Sequence.begin(), Sequence.end(), value), Sequence.end());
    Sequence.erase(std::remove_if(Sequence.begin(), Sequence.end(), predicate), Sequence.end());
    • string
    • array
    • vector
    • deque
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// <algorithm> //< std::remove
template< class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_)
{
    C_.erase(
        std::remove(C_.begin(), C_.end(), V_),
        C_.end()
    );
    return C_;
}
// <algorithm> //< std::remove
template< class TContainer, class TUnaryPredicate >inline
TContainer& remove_if_erase(TContainer& C_, TUnaryPredicate P_)
{
    C_.erase(
        std::remove_if(C_.begin(), C_.end(), P_),
        C_.end()
    );
    return C_;
}

C++11

概要:引数のコンテナが保持するメソッドにより切り分けるアプローチ
ソース:erase_cpp11.hpp (ASCII CR/LF)
  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
//#include <algorithm> //< std::remove
//#include <type_traits> //< std::enable_if
namespace detail {
    template< class TContainer >
    struct has_erase
    {
    private:
        template< class TType >
        static auto isValid(TType V_) -> decltype(V_.erase(std::declval<typename TType::value_type>()), std::true_type());
        static auto isValid(...) -> decltype(std::false_type());
    public:
        typedef decltype(isValid(std::declval<TContainer>())) type;
        static const bool value = type::value;
    };
    template< class TContainer >
    struct has_remove
    {
    private:
        template< class TType >
        static auto isValid(TType V_) -> decltype(V_.remove(std::declval<typename TType::value_type>()), std::true_type());
        static auto isValid(...) -> decltype(std::false_type());
    public:
        typedef decltype(isValid(std::declval<TContainer>())) type;
        static const bool value = type::value;
    };
    template< class TContainer >
    struct has_remove_if
    {
    private:
        struct UnaryPredicate { bool operator()(const typename TContainer::value_type&) const{ return false; } };
        template< class TType >
        static auto isValid(TType V_) -> decltype(V_.remove_if(UnaryPredicate()), std::true_type());
        static auto isValid(...) -> decltype(std::false_type());
    public:
        typedef decltype(isValid(std::declval<TContainer>())) type;
        static const bool value = type::value;
    };
} //< namespace detail
// remove_erase
template< class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_,
    typename std::enable_if<detail::has_erase<TContainer>::value && !detail::has_remove<TContainer>::value, TContainer>::type* = nullptr
) {
    C_.erase(V_);
    return C_;
}
template < class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_,
    typename std::enable_if<!detail::has_erase<TContainer>::value && detail::has_remove<TContainer>::value, TContainer>::type* = nullptr
) {
    C_.remove(V_);
    return C_;
}
template < class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_,
    typename std::enable_if<!detail::has_erase<TContainer>::value && !detail::has_remove<TContainer>::value, TContainer>::type* = nullptr
) {
    C_.erase(std::remove(C_.begin(), C_.end(), V_), C_.end());
    return C_;
}
// remove_erase_if
template < class TContainer, class TUnaryPredicate > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_,
    typename std::enable_if<detail::has_remove_if<TContainer>::value, TContainer>::type* = nullptr
) {
    C_.remove_if(P_);
    return C_;
}
template < class TContainer, class TUnaryPredicate > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_,
    typename std::enable_if<!detail::has_remove_if<TContainer>::value, TContainer>::type* = nullptr
) {
    return remove_erase_if(C_, P_, typename std::iterator_traits< TContainer::iterator >::iterator_category());
}
// for Sequence containers
template< class TContainer, class TUnaryPredicate > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_, std::random_access_iterator_tag)
{
    C_.erase(std::remove_if(C_.begin(), C_.end(), P_), C_.end());
    return C_;
}
// for Associative containers
template< class TContainer, class TUnaryPredicate, class TIteratorTag > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_, TIteratorTag)
{
    typename TContainer::iterator I_ = C_.begin();
    while (I_ != C_.end()) {
        if (P_(*I_)) {
//          C_.erase(I_++);
            I_ = C_.erase(I_);
        } else {
            ++I_;
        }
    }
    return C_;
}
/*
// not_type
template<bool TX_> struct not_type : std::false_type{};
template<> struct not_type<false> : std::true_type{};
// and_type
template<bool TX_, bool TY_> struct and_type : std::false_type{};
template<> struct and_type<true, true> : std::true_type{};

template< class TContainer >
struct enable_if_has_erase
 : std::enable_if<and_type<has_erase<TContainer>::value, not_type<has_remove<TContainer>::value>::value>::value, TContainer> {};

template< class TContainer >
struct enable_if_has_remove
 : std::enable_if<and_type<not_type<has_erase<TContainer>::value>::value, has_remove<TContainer>::value>::value, TContainer> {};

template< class TContainer >
struct enable_if_has_not_remove_erase
 : std::enable_if<and_type<not_type<has_erase<TContainer>::value>::value, not_type<has_remove<TContainer>::value>::value>::value, TContainer> {};

template< class TContainer, class TValue >
void remove_erase(TContainer& C_, const TValue& V_, typename enable_if_has_erase<TContainer>::type* = nullptr)
{ C_.erase(V_); }

template < class TContainer, class TValue >
void remove_erase(TContainer& C_, const TValue& V_, typename enable_if_has_remove<TContainer>::type* = nullptr)
{ C_.remove(V_); }

template < class TContainer, class TValue >
void remove_erase(TContainer& C_, const TValue& V_, typename enable_if_has_not_remove_erase<TContainer>::type* = nullptr)
{ C_.erase(std::remove(C_.begin(), C_.end(), V_), C_.end()); }
*/

C++98

概要:引数のコンテナで切り分けるアプローチ(<list>, <deque>のインクルードが必要)
ソース:erase_cpp98.hpp (ASCII CR/LF)
  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
//#include <algorithm> //< std::remove
//#include <iterator> //< std::iterator_traits
//#include <list>
//#include <deque>

// remove_erase for Sequence containers
template< class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_, std::random_access_iterator_tag)
{
    C_.erase(std::remove(C_.begin(), C_.end(), V_), C_.end());
    return C_;
}
// remove_erase for Associative containers
template< class TContainer, class TValue, class TIteratorTag > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_, TIteratorTag)
{
    C_.erase(V_);
    return C_;
}
template< class TContainer, class TValue > inline
TContainer& remove_erase(TContainer& C_, const TValue& V_)
{
    return remove_erase(C_, V_, typename std::iterator_traits< TContainer::iterator >::iterator_category());
}
template< class TType, class TAlloc, class TValue > inline
std::list<TType, TAlloc>& remove_erase(std::list<TType, TAlloc>& C_, const TValue& V_)
{
    C_.remove(V_);
    return C_;
}
//template< class TType, class TAlloc, class TValue > inline
//std::forward_list<TType, TAlloc>& remove_erase(std::forward_list<TType, TAlloc>& C_, const TValue& V_)
//{
//  C_.remove(V_);
//  return C_;
//}
template< class TType, class TAlloc, class TValue > inline
std::deque<TType, TAlloc>& remove_erase(std::deque<TType, TAlloc>& C_, const TValue& V_)
{
    return remove_erase(C_, V_, std::random_access_iterator_tag());
}


// remove_erase_if for Sequence containers
template< class TContainer, class TUnaryPredicate > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_, std::random_access_iterator_tag)
{
    C_.erase(std::remove_if(C_.begin(), C_.end(), P_), C_.end());
    return C_;
}
// remove_erase_if for Associative containers
template< class TContainer, class TUnaryPredicate, class TIteratorTag > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_, TIteratorTag)
{
    typename TContainer::iterator I_ = C_.begin();
    while (I_ != C_.end()) {
        if (P_(*I_)) {
            C_.erase(I_++);
        } else {
            ++I_;
        }
    }
    return C_;
}
template< class TContainer, class TUnaryPredicate > inline
TContainer& remove_erase_if(TContainer& C_, const TUnaryPredicate& P_)
{
    return remove_erase_if(C_, P_, typename std::iterator_traits< TContainer::iterator >::iterator_category());
}
template< class TType, class TAlloc, class TUnaryPredicate > inline
std::list<TType, TAlloc>& remove_erase_if(std::list<TType, TAlloc>& C_, const TUnaryPredicate& P_)
{
    C_.remove_if(P_);
    return C_;
}
//template< class TType, class TAlloc, class TUnaryPredicate > inline
//std::forward_list<TType, TAlloc>& remove_erase(std::forward_list<TType, TAlloc>& C_, const TUnaryPredicate& P_)
//{
//  C_.remove_if(P_);
//  return C_;
//}
template< class TType, class TAlloc, class TUnaryPredicate > inline
std::deque<TType, TAlloc>& remove_erase_if(std::deque<TType, TAlloc>& C_, const TUnaryPredicate& P_)
{
    return remove_erase_if(C_, P_, std::random_access_iterator_tag());
}

/*
    親クラスのメソッド判定不可

template< class TType, typename TType::size_type (TType::*)(const typename TType::value_type&) >
struct sfinae_helper_4_remove_erase { typedef void type ; };

template< class TType, class TOther = void >
struct has_erase{ enum { value = false }; };

template< class TType >
struct has_erase< TType, typename sfinae_helper_4_remove_erase< TType, &TType::erase >::type >{ enum { value = true }; };

template< class TType, class TOther = void >
struct has_remove{ enum { value = false }; };

template< class TType >
struct has_remove< TType, typename sfinae_helper_4_remove_erase< TType, &TType::remove >::type >{ enum { value = true }; };

*/

unique_erase

概要:重複排除
メモ:
unique()をしただけでは後ろにゴミが残るので、eraseで削除する
unique()を使う準備としてソートが必要
ソース:unique_erase.hpp (ASCII CR/LF)
 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
// <algorithm> //< std::unique
template< class TContainer > inline
typename TContainer::iterator unique_erase(TContainer& C_)
{
    return C_.erase(std::unique(C_.begin(), C_.end()), C_.end());
}
// <algorithm> //< std::unique
template< class TContainer, class TBinaryPredicate > inline
typename TContainer::iterator unique_erase(TContainer& C_, TBinaryPredicate P_)
{
    return C_.erase(std::unique(C_.begin(), C_.end(), P_), C_.end());
}
// <algorithm> //< std::sort
template< class TContainer > inline
typename TContainer::iterator sort_unique_erase(TContainer& C_)
{
    std::sort(C_.begin(), C_.end());
    return unique_erase(C_);
}
// <algorithm> //< std::sort
template< class TContainer, class TBinaryPredicate > inline
typename TContainer::iterator sort_unique_erase(TContainer& C_, TBinaryPredicate P_)
{
    std::sort(C_.begin(), C_.end());
    return unique_erase(C_, P_);
}
/*
// <set>
template< class TContainer > inline
void sort_unique_erase(TContainer& C_)
{
    std::set< typename TContainer::value_type > S_(C_.begin(), C_.end());
    C_.swap(TContainer(S_.begin(), S_.end()));
}
// <set>
// <algorithm> //< std::copy
// <iterator> //< std::iterator_traits
template< class TInputIterator, class TOutputIterator > inline
TOutputIterator sort_unique_copy(TInputIterator F_, TInputIterator L_, TOutputIterator O_)
{
    std::set< typename std::iterator_traits<TInputIterator>::value_type > S_(F_, L_);
    return std::copy(S_.begin(), S_.end(), O_);
}
*/