1

我想用SFINAE原理来检查实例化的模板是否是随机访问迭代器。为此,我使用std::enable_if了 ,但编译器抛出错误:

不能与之前的“类型名称”声明说明符结合

我该如何解决?我真的需要帮助才能弄清楚。

template<class RandomAccessIterator, class Compare>
typename std::enable_if<std::is_same<std::random_access_iterator_tag, RandomAccessIterator>::value>
void quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare) {
    sorting(first, last, 0, last - first - 1, compare);
}
4

2 回答 2

5

我看到的两个问题:

  • 您正在编写std::enable_if<>而不是std::enable_if<>::type,这可能不是您的本意。

  • (错误的原因)您有两种返回类型:std::enable_if<>void. 您只能有一种返回类型。

std::enable_if有第二个可选类型参数,即std::enable_if<>::type. 默认情况下设置为,void因此您的返回类型已经是voidfrom std::enable_if<>::type。但是,由于您要enable_if输入返回类型,我建议您明确指定返回类型为void

因此,您的问题的解决方案如下所示:

template <class RandomAccessIterator, class Compare>
typename std::enable_if<
    std::is_same<std::random_access_iterator_tag, RandomAccessIterator>::value,
    void
>::type quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare) {
    sorting(first, last, 0, last - first - 1, compare);
}

或者,您可以std::enable_if在模板参数中使用:

template <
    class RandomAccessIterator,
    class Compare,
    typename std::enable_if<
        std::is_same<std::random_access_iterator_tag, RandomAccessIterator>::value,
        std::nullptr_t
    >::type = nullptr
>
void quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare) {
    sorting(first, last, 0, last - first - 1, compare);
}
于 2021-09-18T17:07:06.417 回答
4

除了此答案中提到的技术问题外,您的方法根本行不通。

std::is_same<std::random_access_iterator_tag, RandomAccessIterator>::value永远不会评估为真,因为迭代器不是迭代器标记。您需要使用标签调度std::iterator_traits,而不是 SFINAE,来确定传入的迭代器是否是随机访问的。

请参阅 cppreference 上的示例:https ://en.cppreference.com/w/cpp/iterator/iterator_tags

试试这个:

template<class Iter, class Compare>
void quick_sort_impl(Iter first, Iter last, Compare compare, std::random_access_iterator_tag) {
    sorting(first, last, 0, last - first - 1, compare);
}

template<class Iter, class Compare>
void quick_sort(Iter first, Iter last, Compare compare) {
    quick_sort_impl(first, last, compare, typename std::iterator_traits<Iter>::iterator_category());
}

这样,如果您尝试quick_sort()使用非随机访问的迭代器进行调用,由于缺少quick_sort_impl()非随机迭代器标签的重载,您将收到编译器错误。如果要对其他类型的迭代器实现排序,只需quick_sort_impl()根据需要对其他类型的迭代器标签进行重载即可。

于 2021-09-18T18:17:32.060 回答