Efficient static dispatch

Hans Dembinski

TU Dortmund

Take-home message

Basic find

Better find

// simple find, has O(N) complexity
template <class Container, class Value>
auto find(Container const& c, Value const& v) {
  // ADL-friendly use of begin, end
  using std::begin; using std::end;
  return std::find(begin(c), end(c), v);
}

// specialization for std::set, has O(logN) complexity
template <class K, class C, class A>
auto find(std::set<K, C, A> const& s, V const& v) {
  return s.find(v);
}

Generic find

template <class Container, class Value>
auto find(Container const& c, Value const& v) {
  // ADL-friendly use of begin, end
  using std::begin; using std::end;
  return std::find(begin(c), end(c), v);
}

// implementation for set-like, delegates to `find` method, if it exists
template <class Set, class Value>
auto find(Set const& s, Value const& v) -> decltype(s.find(v)) {
  return s.find(v);
}

Fighting ambiguity

error: call of overloaded 'find(std::set<int> const&, int)' is ambiguous

Resolving ambiguity

// helper class to resolve ambiguity by hand
template <int N>
struct priority : priority<N-1> {}; // derived class

template <>
struct priority<0> {}; // base class

template <class Container, class Value>
auto find_impl(Container const& c, Value const& v, priority<0>) {
  using std::begin; using std::end;
  return std::find(begin(c), end(c), v); // delegate to stdlib
}

template <class Container, class Value>
auto find_impl(Container const& c, Value const& v, priority<1>) -> decltype(c.find(v)) {
  return c.find(v); // use that find method if it exists
}

template <class Container, class Value>
auto find(Container const& c, Value const& v) {
  return find_impl(c, v, priority<1>{}); // calls find_impl with highest priority that passes substitution test
}

Summary