选择基于iterator :: value_type的函数实现

时间:2014-08-01 14:04:57

标签: templates c++11 enable-if

我正在寻找一种合理的方法来根据容器的值类型选择排序算法。

在当前形式中,我可以推导出整数/非整数数据的正确sort(a, b)

#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. 我希望能够使用类似数组的迭代器。 (他们没有:: value_type)。
  2. 我希望能够区分say,int32_t和int64_t。
  3. 我完全失去了如何以任何相当简单的方式实现这一目标。即并非专门针对每个实例。

1 个答案:

答案 0 :(得分:4)

使用std::iterator_traits<T>::value_type检索迭代器的值类型;它适用于指针以及类类型迭代器。

对于调度,我会使用模板专精来选择正确的实现(Live Demo):

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

您可能应该约束sort_selector::sort以要求随机访问迭代器,以便当有人不可避免地尝试传递不正确的迭代器类型时,您的错误消息会更容易理解:

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