我想使用SFINAE原则来检查实例化的模板是否是随机访问迭代器。为此,我使用了std::enable_if
,但是编译器抛出了一个错误:
不能与前面的'type-name'声明说明符组合
我该如何修复它?我真的需要你的帮助来解决这个问题。
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);
}
我看到两个问题:
-
你写的是
std::enable_if<>
而不是std::enable_if<>::type
,这可能不是你想要做的。 -
(错误原因)有两种返回类型:
std::enable_if<>
和void
。你只能有一个返回类型
std::enable_if
有第二个可选的类型参数,该参数是std::enable_if<>::type
的类型。默认设置为void
,因此您的返回类型已经从std::enable_if<>::type
变为void
。但是,由于您将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);
}
除了回答中提到的技术问题外,您的方法根本行不通。
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()
即可。