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:
template
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:
template
using VectorView = ContainerView
template
using ListView = ContainerView
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:
template
typename View::Iterator CreateLists(typename View::Iterator first, typename View::Iterator end, View& list)
{
list = View(first, end);
return end;
}
template
typename View::Iterator CreateLists(typename View::Iterator first, typename View::Iterator end, View& list, const std::function
{
auto firstNonExtracted = std::stable_partition(first, end, extracter);
list = View(first, firstNonExtracted);
return firstNonExtracted;
}
template
void CreateLists(typename View::Iterator first, typename View::Iterator end, View& list, const std::function
{
auto newFirst = CreateLists
CreateLists
}
Enfin, petite mise à jour similaire pour notre petite fonction d'affichage de collection:
template
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 !
int main()
{
{
std::vector
for (int i = 0; i < 100; ++i)
values.push_back(i);
VectorView
VectorView
VectorView
VectorView
VectorView
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
for (int i = 0; i < 100; ++i)
values.push_back(i);
ListView
ListView
ListView
ListView
ListView
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;
}
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.