2017-08-05 2 views
-3

Supposons que je souhaite implémenter une classe qui itère sur une certaine plage et stocke ces valeurs dans un tableau à des index aléatoires. Donc, je veux quelque chose où je peux écrire:Classe qui accepte l'itérateur comme argument et stocke les valeurs?

string s = "Steve"; 
auto r1 = RandomArray<char>(s.begin(), s.end()); 
int a[] = {1,2,3}; 
auto r2 = RandomArray<int>(begin(a), end(a)); 
// Later on... 
for (const auto ch: r1) {/* do something */} 

Comment pourrais-je définir une telle classe? Je ne peux pas comprendre à quoi devrait ressembler le modèle. C'est, comment puis-je remplir ce qui manque ci-dessous? J'ignore toutes les autres choses dont j'ai besoin (déplacer des constructeurs, commencer/terminer, etc.). Je veux juste comprendre ce que l'énoncé de modèle avant la classe devrait ressembler.

+0

Ce que vous cherchez vraiment sont des guides de déduction de modèle spécifié par l'utilisateur, qui ont été introduites en C++ 17. –

+0

Vous attendez-vous à ce que le type de 'arr_' ​​dépende magiquement du constructeur' RandomArray' qui a été appelé lors de l'exécution? Ça ne va pas voler. Vous pouvez faire 'RandomArray' un template de classe paramétré sur le type de l'élément, puis un template de fonction comme' MakeRandomArray' va fabriquer la spécialisation correcte basée sur ses arguments. Similaire à 'std :: make_pair'. Ou, il est possible que j'ai complètement mal compris la nature du problème; une explication plus complète du but ultime de l'exercice pourrait aider. –

+0

@IgorTandetnik: Je voudrais que le type d'arr_ corresponde au type de valeur de l'itérateur. Je ne sais pas comment exprimer cela. Le but des constructeurs "encore meilleurs" est de simplement souligner que je ne veux pas passer le début/fin, mais plutôt l'itérable lui-même. Vous pouvez le considérer comme secondaire à la question principale. –

Répondre

1

Quelque chose le long de ces lignes (non testé):

template <typename Elem> 
class RandomArray { 
public: 
    template <typename InputIter> 
    RandomArray(InputIter first, InputIter last) 
    : storage(first, last) {} 

    template <typename Container> 
    explicit RandomArray(const Container& c) 
    : storage(std::cbegin(c), std::cend(c)) {} 

    // For C-style array 
    template <typename Elem2, size_t N> 
    explicit RandomArray(Elem2 (&arr)[N]) 
    : storage(std::cbegin(arr), std::cend(arr)) {} 

private: 
    std:vector<Elem> storage; 
}; 

template <typename InputIter> 
auto MakeRandomArray(InputIter first, InputIter last) { 
    return RandomArray<typename std::iterator_traits<InputIter>::value_type>(
    first, last); 
} 

template <typename Container> 
auto MakeRandomArray(const Container& c) { 
    return RandomArray<typename Container::value_type>(c); 
} 

// For C-style array 
template <typename Elem, size_t N> 
auto MakeRandomArray(Elem (&arr)[N]) { 
    return RandomArray<Elem>(arr); 
} 
+0

Très agréable, semble fonctionner! –