[Actualité] [Aller plus loin]Extraire des collections de données depuis une collection initiale
par
, 04/11/2020 à 16h11 (4552 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:
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
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; };
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:
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
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)...); }
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; }