
On Thu, May 27, 2010 at 1:38 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote:
How do I use Boost.ConceptCheck and/or Bosot.EnableIf to implement concept-based overloading (as discussed in N2081)?
How do I program this in C++ using Boost libraries?
N2081 briefly mentions this can be done in C++ using SFINAE, etc. I think I could use `enable_if` if I had some sort of `is_input_iterator` metafunction..
You pretty much need to use tag dispatching to be able to handle concept-based overloading with refinement of concepts, rather than straight SFINAE. The main reason for this is most easily shown with some pseudo code: // Imagine that these represent true overloads based on concepts void foo( forward_iterator it ); // foo 1 void foo( random_access_iterator it ); // foo 2 // SFINAE enable_if-style expressions template< typename T > typename enable_if< is_forward_iterator< T > >::type bar( T it ); // bar 1 template< typename T > typename enable_if< is_random_access_iterator< T > >::type bar( T it ); // bar 2 Now do "foo( some_std_list.begin() )". As you'd expect, foo 1 is called. Similarly, do "bar( some_std_list.begin() )". Again, as you'd expect, bar 1 is called However, what if you call "foo( some_std_vector.begin() );" foo 2 is of course called, but if you do "bar( some_std_vector.begin() )" your expression is now ambiguous since T is a random access iterator, which in turn is also a forward iterator via refinement. Both overloads are valid candidates with one no better than the other. The "foo" example works because foo 2 is a better match than foo 1, but with a basic SFINAE approach, that is not the case. The way the desired behavior is simulated in C++, as you are probably familiar with already, is tag dispatch, where the tags are related directly in C++ through inheritance, allowing the compiler to pick the better match via overload rules with regard to inheritance for the tag parameter. There are ways you can probably think of, avoiding tag dispatch, to get the overloads in the "bar" example to be picked as you'd like for this simple case, but it would be tough to make the overloads "future proof" with respect to unknown refinements and overloads that may be written at some later point in time. With tag dispatch, no such problem exists and writing overloads is still fairly intuitive. Unfortunately, even in C++0x, I personally do not believe that there is a better way to do this without tag dispatch. -- -Matt Calabrese