0

I've seen various SFINAE-related answers regarding calling a function conditionally depending on whether or not a class has a certain function. They're mostly different from what I'm trying to achieve, so I haven't been able to translate it into my project.

I have an algorithm that iterates through a collection and does some stuff. The algo relies on the collection being sorted. I want to be able to feed the algo either a set (which is sorted internally and does NOT have a "sort" function), or a list (which is not sorted, and DOES have a "sort" function).

I want to make my solution more generic than just for set or list. I want there to be a single function which will call the sort method on the template type if it exists, and not otherwise.

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

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

I thought if I feed a std::set to the first function it'll fail to instantiate because std::set::sort doesn't exist, then it'll attempt to instantiate the second one and succeed.

I also tried adding std::enable_if to the template of the first function:

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

but got:

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

Not sure how to proceed. Thanks!

Ken Garber
  • 51
  • 7
  • 1
    `std::is_member_function_pointer` doesn't have a `type` member. It has a `value` member. – aschepler Oct 18 '19 at 22:26
  • 1
    Fundamentally, what are you going to do if I pass a `std::unordered_set` which is neither sorted, nor can be sorted? – walnut Oct 18 '19 at 22:35
  • 2
    Possible duplicate of [Is it possible to write a template to check for a function's existence?](https://stackoverflow.com/questions/257288/is-it-possible-to-write-a-template-to-check-for-a-functions-existence) – walnut Oct 18 '19 at 22:44
  • 1
    Search the duplicate's answers for the C++ standard version that you are using, because the overhead required went down with each new version. – walnut Oct 18 '19 at 22:45

1 Answers1

0

Answering my own question.

Thanks uneven_mark for pointing out the possible duplicate (Is it possible to write a template to check for a function's existence?). I'm using GCC 6.x which supports C++ 17 but not if-constexpr, so that solution didn't work entirely.

Taking that answer as inspiration, here's my solution:

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);
}

As uneven_mark points out, I'll need to handle the case where a container is both unsorted and doesn't have a sort function.

Ken Garber
  • 51
  • 7