Voir le flux RSS

Bousk

[Actualité] [Aller plus loin]Extraire des collections de données depuis une collection initiale

Note : 5 votes pour une moyenne de 2,60.
par , 04/11/2020 à 16h11 (1525 Affichages)
Dans le billet précédent, nous avons vu comment extraire des collections de données depuis un vector sans aucune allocation supplémentaire.
La conclusion laissait entendre que ce système est applicable à d'autres collections que std::vector.

Ça l'est, et relativement simplement.

Pour y parvenir, il suffit d'ajouter un niveau de template, en modifiant le template pour pas être le type de l'élément mais de la collection.
Ainsi, VectorView devient donc ContainerView:
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <class Container>
class ContainerView
{
public:
    using Type = Container;
    using Element = typename Type::value_type;
    using Iterator = typename Type::iterator;
    using ConstIterator = typename Type::const_iterator;
public:
    ContainerView()
    {
        // Default values to prevent iterating over random memory
        m_begin = m_end;
    }
    ContainerView(typename ConstIterator first, typename ConstIterator end)
        : m_begin(first)
        , m_end(end)
    {}
    ConstIterator begin() const { return m_begin; }
    ConstIterator end() const { return m_end; }
private:
    typename ConstIterator m_begin, m_end;
};
Et nous pouvons créer des allias pour continuer à utiliser VectorView aisément:
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
template<class T>
using VectorView = ContainerView<std::vector<T>>;
template<class T>
using ListView = ContainerView<std::list<T>>;

Il faut propager le changement aux fonctions.
Les plus attentifs auront remarqué que des allias sur le container interne, ses itérateurs et le type interne ont été ajouté à ContainerView. La syntaxe correspond aux types de std, mais peut être adaptée à vos propres collections.
Ceci permet de simplifier son utilisation, en passant un unique paramètre template qui sera la vue:
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
template<class View>
typename View::Iterator CreateLists(typename View::Iterator first, typename View::Iterator end, View& list)
{
    list = View(first, end);
    return end;
}
template<class View>
typename View::Iterator CreateLists(typename View::Iterator first, typename View::Iterator end, View& list, const std::function<bool(typename View::Element)>& extracter)
{
    auto firstNonExtracted = std::stable_partition(first, end, extracter);
    list = View(first, firstNonExtracted);
    return firstNonExtracted;
}
template<class View, class... Args>
void CreateLists(typename View::Iterator first, typename View::Iterator end, View& list, const std::function<bool(typename View::Element)>& extracter, Args&&... args)
{
    auto newFirst = CreateLists<View>(first, end, list, extracter);
    CreateLists<View>(newFirst, end, std::forward<Args>(args)...);
}
Enfin, petite mise à jour similaire pour notre petite fonction d'affichage de collection:
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
template<class View>
void PrintValues(const char* name, View values)
{
    std::cout << name << " : ";
    for (auto&& value : values)
        std::cout << value << ", ";
    std::cout << std::endl;
}

L'utilisation est identique, voire simplifiée : le paramètre template à l'appel de CreateLists, que VS2019 ne semblait pas pouvoir déduire et était obligatoire dans le premier billet, ne l'est plus !
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
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
int main()
{
    {
        std::vector<int> values;
        for (int i = 0; i < 100; ++i)
            values.push_back(i);
 
        VectorView<int> pairs;
        VectorView<int> mul3;
        VectorView<int> mul5;
        VectorView<int> mul7;
        VectorView<int> others;
 
        CreateLists(values.begin(), values.end()
            , pairs, [](int v) { return v % 2 == 0; }
        , mul3, [](int v) { return v % 3 == 0; }
        , mul5, [](int v) { return v % 5 == 0; }
        , mul7, [](int v) { return v % 7 == 0; }
            , others
            );
 
        PRINT_VALUES_WITH_NAME(pairs);
        PRINT_VALUES_WITH_NAME(mul3);
        PRINT_VALUES_WITH_NAME(mul5);
        PRINT_VALUES_WITH_NAME(mul7);
        PRINT_VALUES_WITH_NAME(others);
    }
    {
        std::list<int> values;
        for (int i = 0; i < 100; ++i)
            values.push_back(i);
 
        ListView<int> pairs;
        ListView<int> mul3;
        ListView<int> mul5;
        ListView<int> mul7;
        ListView<int> others;
 
        CreateLists(values.begin(), values.end()
            , pairs, [](int v) { return v % 2 == 0; }
            , mul3, [](int v) { return v % 3 == 0; }
            , mul5, [](int v) { return v % 5 == 0; }
            , mul7, [](int v) { return v % 7 == 0; }
            , others
            );
 
        PRINT_VALUES_WITH_NAME(pairs);
        PRINT_VALUES_WITH_NAME(mul3);
        PRINT_VALUES_WITH_NAME(mul5);
        PRINT_VALUES_WITH_NAME(mul7);
        PRINT_VALUES_WITH_NAME(others);
    }
 
	return 0;
}

Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Viadeo Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Twitter Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Google Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Facebook Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Digg Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Delicious Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog MySpace Envoyer le billet « [Aller plus loin]Extraire des collections de données depuis une collection initiale » dans le blog Yahoo

Mis à jour 04/11/2020 à 18h48 par Bousk

Catégories
Programmation , C++

Commentaires