En supposant que la classe est définit comme suit:
template <class T>
class Foo
{
public:
[..]
private:
std::vector<T> m_data;
}
Brisons cette tâche en sous-tâches:
Construct de itérateurs
template <class Iterator>
Foo (Iterator begin, Iterator end, typename Iterator::iterator_category * = 0)
: m_data(begin, end);
Nous allons remplir notre m_data
à partir de begin
et end
.
Le troisième paramètre s'assurera que seuls les types Iterator
qui déclarent iterator_category
correspondent à ce prototype. Puisque cet argument a une valeur par défaut de 0
et n'est jamais spécifié, il sert uniquement à un but pendant le processus de déduction de modèle. Lorsque le compilateur vérifie s'il s'agit du bon prototype, si le type Iterator::iterator_category
n'existe pas, il l'ignorera. Puisque iterator_category
est un type indispensable pour chaque itérateur standard, il fonctionnera pour eux.
Cette c'tor permettra aux appels suivants:
std::vector<int> vec = {1, 2, 3, 4};
Foo<int> f(vec.begin(), vec.end());
-- AND --
std::list<std::size_t> list = {1, 2, 3, 4};
Foo<int> f(list.begin(), list.end());
Construct du contenant
template <class Container>
Foo (const Container & container, decltype(std::begin(container))* = 0, decltype(std::end(container))* = 0)
: m_data(std::begin(container), std::end(container));
Nous remplirons notre m_data
du récipient donné. Nous itérer dessus en utilisant std::begin
et std::end
, car ils sont plus génériques que leurs homologues .begin()
et .end()
et supportent plus de types, par ex. tableaux primitifs. Cette c'tor permettra aux appels suivants:
std::vector<int> vec = {1, 2, 3, 4};
Foo<int> f(vec);
-- AND --
std::list<std::size_t> list = {1, 2, 3, 4};
Foo<int> f(list);
-- AND --
std::array<int,4> arr = {1, 2, 3, 4};
Foo<int> f(arr);
-- AND --
int arr[] = {1, 2, 3, 4};
Foo<int> f(arr);
Construct à partir d'une liste initialiseur
template <class X>
Foo (std::initializer_list<X> && list)
: m_data(std::begin(list), std::end(list));
Note: Nous prenons la liste comme rvalue référence comme il est généralement le cas , mais nous pourrions également ajouter un Foo (const std::initializer_list<X> & list)
pour soutenir la construction de Lvalues.
Nous remplissons notre m_data
en itérant de nouveau sur la liste.Et ce c'tor soutiendra:
Foo<int> f1({1});
Foo<int> f2({1, 2});
Foo<int> f3({1, 2, 3});
Foo<int> f4({1, 2, 3, 4});
Constructor du nombre variable d'arguments
template <class ... X>
Foo (X ... args) {
int dummy[sizeof...(args)] = { (m_data.push_back(args), 0)... };
static_cast<void>(dummy);
}
Ici, remplir les données dans le récipient est un peu plus délicat. Nous utilisons l'expansion des paramètres pour décompresser et pousser chacun des arguments. Cette c'tor nous permet d'appeler:
Foo<int> f1(1);
Foo<int> f2(1, 2);
Foo<int> f3(1, 2, 3);
Foo<int> f4(1, 2, 3, 4);
classe entière
Le résultat final est très agréable:
template <class T>
class Foo
{
public:
Foo() {
std::cout << "Default" << std::endl;
}
template <class ... X>
Foo (X ... args) {
int dummy[sizeof...(args)] = { (m_data.push_back(args), 0)... };
static_cast<void>(dummy);
std::cout << "VA-args" << std::endl;
}
template <class X>
Foo (std::initializer_list<X> && list)
: m_data(std::begin(list), std::end(list)) {
std::cout << "Initializer" << std::endl;
}
template <class Container>
Foo (const Container & container, decltype(std::begin(container))* = 0, decltype(std::end(container))* = 0)
: m_data(std::begin(container), std::end(container)) {
std::cout << "Container" << std::endl;
}
template <class Iterator>
Foo (Iterator first, Iterator last, typename Iterator::iterator_category * = 0)
: m_data(first, last) {
std::cout << "Iterators" << std::endl;
}
private:
std::vector<T> m_data;
};
Je ne suis pas sûr que le problème est aussi simple que vous croyez c'est. –
Pouvez-vous montrer ce que vous avez essayé et ses erreurs? Avec une description de ce que vous voulez travailler –