C++ SFINAE:如果可能,对标准集合进行排序

C++ SFINAE: sort a std collection if possible

我看到过各种与 SFINAE 相关的答案,这些答案是关于根据 class 是否具有特定函数来有条件地调用函数的。它们与我想要实现的目标大不相同,因此我无法将其转化为我的项目。

我有一个算法可以遍历一个集合并做一些事情。该算法依赖于正在排序的集合。我希望能够为算法提供一个集合(它在内部排序并且没有 "sort" 函数),或者一个列表(它没有排序,并且确实有一个 "sort" 函数) .

我想让我的解决方案比集合或列表更通用。我希望有一个单独的函数,如果模板类型存在,它将调用 sort 方法,否则不调用。

template <class Container>
void algo(Container container) {
  container.sort();
  algoHelper(container);
}

template <class Container>
void algo(Container container) {
  algoHelper(contiainer);
}

我认为如果我将 std::set 提供给第一个函数,它将无法实例化,因为 std::set::sort 不存在,然后它将尝试实例化第二个函数并成功。

我也试过在第一个函数的模板中添加std::enable_if:

template <typename Container,
          typename std::enable_if_t<std::is_member_function_pointer<decltype(&Container::sort)>::type>>

但得到了:

error: no matching function for call to 'algo(std::__cxx11::list<int>)'

不确定如何进行。谢谢!

回答我自己的问题。

感谢 uneven_mark 指出可能的重复项 (Is it possible to write a template to check for a function's existence?)。我正在使用支持 C++ 17 但不支持 if-constexpr 的 GCC 6.x,因此该解决方案无法完全工作。

以这个答案为灵感,这是我的解决方案:

template<typename T>
using sort_t = decltype( std::declval<T&>().sort() );

template<typename T>
constexpr bool has_sort = std::experimental::is_detected_v<sort_t, T>;

template <class Container>
std::enable_if_t<has_sort<Container>, void>
algo(Container container) {
  container.sort();
  algoHelper(container);
}

template <class Container>
std::enable_if_t<!has_sort<Container>, void>
algo(Container container) {
  algoHelper(contiainer);
}

正如 uneven_mark 指出的那样,我需要处理容器既未排序又没有排序功能的情况。