
On Tue, Sep 28, 2010 at 3:36 PM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On Tue, Sep 28, 2010 at 1:48 PM, joel falcou <joel.falcou@lri.fr> wrote:
On 28/09/10 19:37, David Abrahams wrote:
This BehaveAsPair thing doesn't identify any real abstraction. I promise you're not going to come across any uses for BehaveAsPair other than in solving the exact implementation problem you're attacking.
I see
In short, it lacks "truthiness." :-)
Agreed
Was there something unsatisfying about the solution I posted in http://permalink.gmane.org/gmane.comp.lib.boost.devel/209012 ?
Nope, I just missed it.
Oh wait! I think I have another example that's more truthy. :) I'll use Boost.ConceptCheck to flesh it out. Let's define the concept of an AdditivePair to represent the arguments to binary addition. To model the concept a type needs to support first(x), second(x) and add(x) for an object x where all three functions have integer values. So, the (simplest) concept checking class would be:
template <class T> struct AdditivePair { BOOST_CONCEPT_USAGE(AdditivePair) { int a = first(x); int b = second(x); int c = add(x); } T x; };
We can now write Eric's function using concept requirements.
template<class T> BOOST_CONCEPT_REQUIRES( ((AdditivePair<T>)), (int) ) sum_ints( T const & t ) { return add( t ); }
We can now adapt std::pair<int,int> to model the AdditivePair concept.
int first(std::pair<int,int> x) { return x.first; } int second(std::pair<int,int> x) { return x.second; } int add(std::pair<int,int> x) { return first(x) + second(x); }
And we can also adapt int to model the AdditivePair concept; i.e. int is an additive pair where the second member is 0.
int first(int x) { return x; } int second(int x) { return 0; } int add(int x) { return x; }
That seems pretty natural to me.
Crap. I just realized that Eric's original function was recursive! Doh! Let me try that again. To handle recursive pairs the AdditivePair concept needs a pair_traits class, which will determine the return types of first(x) and second(x). The concept checking class is almost the same as before: template<class> struct pair_traits; template <class T> struct AdditivePair { BOOST_CONCEPT_USAGE(AdditivePair) { typename pair_traits<T>::first_type a = first(x); typename pair_traits<T>::second_type b = second(x); int c = add(x); } T x; }; Eric's function can still use concept requirements. In fact, no changes are required for the recursive version. template<class T> BOOST_CONCEPT_REQUIRES( ((AdditivePair<T>)), (int) ) sum_ints( T const & t ) { return add( t ); } Adapting pair<int,int> and int to model AdaptivePair is basically the same, but now we need to specialize the traits class. // adapt pair int first(std::pair<int,int> x) { return x.first; } int second(std::pair<int,int> x) { return x.second; } int add(std::pair<int,int> x) { return first(x) + second(x); } template<> struct pair_traits<std::pair<int,int> > { typedef int first_type; typedef int second_type; }; // adapt int int first(int x) { return x; } int second(int x) { return 0; } int add(int x) { return x; } template<> struct pair_traits<int> { typedef int first_type; typedef int second_type; }; And now we can adapt recursive pairs to model the AdditivePair concept. template<class T0, class T1> T0 first(std::pair<T0,T1> x) { return x.first; } template<class T0, class T1> T1 second(std::pair<T0,T1> x) { return x.second; } template<class T0, class T1> int add(std::pair<T0,T1> x) { return add(first(x)) + add(second(x)); } template<class T0, class T1> struct pair_traits<std::pair<T0,T1> > { typedef T0 first_type; typedef T1 second_type; }; Now that works as expected. Sorry for any confusion. (It illustrates an interesting point, though. I was concerned with the base case in Eric's recursion where I a saw unary function called sum_ints, which didn't make sense to me conceptually since addition is a binary operation. So, I was focused on trying to work out the concept modeled by the argument to sum_ints, and missed the fact that sum_ints was recursive. Later, though, having the concept worked out made implementing the recursive version trivial.) Daniel Walker