C ++ SFINAE: сортируйте коллекцию std, если это возможно - PullRequest
0 голосов
/ 19 октября 2019

Я видел различные ответы, связанные с SFINAE, относительно условного вызова функции в зависимости от того, имеет ли класс определенную функцию. Они в основном отличаются от того, чего я пытаюсь достичь, поэтому я не смог перевести это в свой проект.

У меня есть алгоритм, который перебирает коллекцию и выполняет некоторые вещи. Алгоритм полагается на сортировку коллекции. Я хочу иметь возможность кормить алгоритм либо набором (который отсортирован внутри и НЕ имеет функции «сортировки»), либо списком (который не отсортирован, и имеет функцию «сортировки»).

Я хочу сделать свое решение более общим, чем просто набор или список. Я хочу, чтобы была одна функция, которая будет вызывать метод сортировки по типу шаблона, если он существует, а не иначе.

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>)'

Не уверенкак продолжить. Спасибо!

1 Ответ

0 голосов
/ 21 октября 2019

Отвечая на мой собственный вопрос.

Спасибо uneven_mark за указание на возможный дубликат ( Можно ли написать шаблон для проверки существования функции? ). Я использую GCC 6.x, который поддерживает C ++ 17, но не if-constexpr, так что решение не работает полностью.

Принимая этот ответ как вдохновение, вот мое решение:

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, мне нужно разобраться со случаем, когда контейнер не отсортирован и не имеет функции сортировки.

...