Question

Je suis à la recherche d'un moyen raisonnable de sélectionner un algorithme de tri basé sur le type de la valeur du conteneur.

Dans sa forme actuelle, je peux en déduire le bon sort(a, b) pour entier/données non entier.

#include <cstdlib>
#include <type_traits>
#include <algorithm>
#include <vector>
#include <iostream>

namespace sort_selector{
    template<typename T>
    void _radix_sort(T begin, T end){
        // radix implementation
    }

    template<typename T>
    typename std::enable_if<
                  std::is_integral<typename T::value_type>::value>::type
    sort(T begin, T end){
        std::cout << "Doing radix" << std::endl;
        sort_selector::_radix_sort(begin, end);
    }

    template<typename T>
    typename std::enable_if<
                  !std::is_integral<typename T::value_type>::value>::type
    sort(T begin, T end){
        std::cout << "Doing sort" << std::endl;
        std::sort(begin, end);
    }
}
int main(int argc, char** argv) {
    std::vector<double> for_stdsort = {1, 4, 6, 2};
    std::vector<int32_t> for_radixsort = {1, 4, 6, 2};
    //std::array<int32_t, 4> array_for_radixsort = {1, 4, 6, 2};

    sort_selector::sort(std::begin(for_stdsort), std::end(for_stdsort));
    sort_selector::sort(std::begin(for_radixsort), std::end(for_radixsort));
    //sort_selector::sort(std::begin(array_for_radixsort), 
    //                     std::end(array_for_radixsort));

    return 0;
}
  1. Je voudrais être en mesure d'utiliser semblable au tableau des itérateurs.(ils n'ont pas d' ::value_type).
  2. Je voudrais être capable de distinguer entre les dire, int32_t et int64_t.

Je suis à une perte complète que la façon de réaliser cela dans toute raisonnablement simple.I. e.non spécialisée pour chaque instance.

Était-ce utile?

La solution

Utilisation std::iterator_traits<T>::value_type pour récupérer le type de la valeur de l'itérateur;il fonctionne pour les pointeurs ainsi que la classe de type itérateurs.

Pour la distribution, je voudrais utiliser un modèle de spécialisation pour sélectionner la bonne mise en œuvre (Démonstration En Direct):

namespace sort_selector {
// Default to using std::sort
template <typename T, typename = void>
struct dispatcher {
  template <typename Iterator>
  static void sort(Iterator begin, Iterator end) {
    std::cout << "Doing std::sort\n";
    std::sort(begin, end);
  }
};

// Use custom radix sort implementation for integral types
template <typename T>
struct dispatcher<T, typename std::enable_if<std::is_integral<T>::value>::type> {
  template <typename Iterator>
  static void sort(Iterator, Iterator) {
    std::cout << "Doing radix\n";
    // radix implementation
  }
};

// Use some other specific stuff for int32_t
template <>
struct dispatcher<int32_t, void> {
  template <typename Iterator>
  static void sort(Iterator, Iterator) {
    std::cout << "Specific overload for int32_t\n";
    // Do something
  }
};

// Dispatch appropriately
template <typename Iterator>
inline void sort(Iterator begin, Iterator end) {
  dispatcher<typename std::iterator_traits<Iterator>::value_type>::sort(begin, end);
}
} // namespace sort_selector

Vous devriez probablement contraindre sort_selector::sort d'exiger des itérateurs à accès aléatoire de sorte que vos messages d'erreur sont plus digestibles inévitablement quand quelqu'un essaie de passer une mauvaise itérateur de type:

namespace sort_selector {
// Dispatch appropriately
template <typename Iterator>
inline void sort(Iterator begin, Iterator end) {
  using traits = std::iterator_traits<Iterator>;
  static_assert(
    std::is_base_of<
      std::random_access_iterator_tag,
      typename traits::iterator_category
    >::value, "sorting requires random access iterators");
  dispatcher<typename traits::value_type>::sort(begin, end);
}
} // namespace sort_selector
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top