Picking overload with the most specific concept

Hi, I was playing around today and I achieved to do something I find quite cool. I would like to know whether the technique/general principle is of any interest. Basically, it allows to overload functions based on the modeling of a concept by a type without having to write complicated enable_ifs. It does come with some problems and it is not very general for the moment, but it's a first shot. Here we go: #include <duck.hpp> // the library where I implemented that #include <forward_list> #include <utility> #include <vector> // Generates some boilerplate required to enable concept overloading for // a function named `my_distance`. Ignore this for now. DUCK_ENABLE_CONCEPT_OVERLOADING( my_distance, my_distance(std::declval<Iterator>(), std::declval<Iterator>(), State()), typename Iterator ) struct random_access_version_picked { }; struct forward_version_picked { }; // The State template parameter will be used to carry information during // the resolution. tag::my_distance was defined by the above macro. template <typename Iterator, typename State = tag::my_distance> // This can be seen like an enable_if with some more functionality. typename duck::requires< // This overload is picked iff Iterator models RandomAccessIterator // and no other overload for a more specific concept exist. // Concepts are MPL metafunction classes, so there's no magic here. duck::model_of<duck::RandomAccessIterator, Iterator> // Could add more duck::model_of clauses here , duck::overload_resolution_state<State> // required for the mechanics , duck::template_parameters<Iterator> // ditto , random_access_version_picked>::type // return type my_distance(Iterator, Iterator, State = State()) { return random_access_version_picked(); } // Same thing for the ForwardIterator implementation. template <typename Iterator, typename State = tag::my_distance> typename duck::requires< duck::model_of<duck::ForwardIterator, Iterator> , duck::overload_resolution_state<State> , duck::template_parameters<Iterator> , forward_version_picked>::type my_distance(Iterator, Iterator, State = State()) { return forward_version_picked(); } int main() { std::forward_list<int> list; std::vector<int> vec; forward_version_picked forward = my_distance(begin(list), end(list)); random_access_version_picked random = my_distance(begin(vec),end(vec)); } This example works with Clang 3.3 and GCC 4.8. For those interested in seeing more, the full library is available at: http://github.com/ldionne/duck Look for the `next` branch. The file involved with the above mechanics is include/duck/requires.hpp. Also see the test in test/requires.cpp. Regards, Louis Dionne
participants (1)
-
Louis Dionne