
At Wed, 13 Oct 2010 10:09:39 -0700, Steven Watanabe wrote:
AMDG
Sorry for the delayed response.
Back atcha! Been looking forward to getting back to this thread.
As an example, let's use the fusion::less algorithm.
I was actually using a simplified version that requires both sequences to be the same type. (And thus the same length). A full lexicographical comparison is fine though.
Close. What you need is a refined concept for NonEmptyFusionSequence that includes front_type and pop_front. Just riffing here, but this could work:
concept FusionSequence<class S> { CompileTimeInt size_type = int_<0>;
constexpr bool empty(const S&) { return size_type::value; } constexpr std::size_t size(const S&) { return size_type::value; } }
auto concept NonEmptyFusionSequence<class S> : FusionSequence<S> { FusionSequence next_type; next_type pop_front(const S&);
typename front_type; front_type front(const S&);
CompileTimeInt size_type = int_<next_type::size_t::value+1>; };
// A shorter way. Because of refinement, this one will only get // used when either S1 or S2 is empty.
template<FusionSequence S1, FusionSequence S2> // a constraint you could add for clarity, but don't need // requires SameType<int_<0>, int_<S1::size_type()*S2::size_type()> > concept_map LessThanComparable<S1,S2> { constexpr operator<(S1 const&, S2 const&) { return S1::size_type()< S2::size_type(); } }
Isn't the extra constraint needed to make sure that trying to compare sequences whose elements are /not/ LessThanComparable won't silently misbehave?
I see what you mean; I overlooked that issue. Technically the correct answer is that I guess it depends on your desired semantics; as I coded it, it would mean make_tuple(1, 2) < make_tuple("a", "b", "c") is that misbehavior? Well, I guess it's not what tuple is currently specified to do, so maybe it is.
template<NonEmptyFusionSequence S1, NonEmptyFusionSequence S2> requires LessThanComparable<S1::front_type,S2::front_type> && LessThanComparable<S1::next_type,S2::next_type> concept_map LessThanComparable<S1,S2> { operator<(S1 const& x, S2 const& y) { return front(x)< front(y) || pop_front(x)< pop_front(y) } }
Okay. Here's why I don't like this.
Suppose that I define a second algorithm with exactly the same requirements.
So the first algorithm is fusion::less. If you accept the above concept_maps, fusion::less would just look like: template <FusionSequence S1, FusionSequence S2> requires LessThanComparable<S1,S2> bool less(S1 const& x, S2 const& y) { return x < y; }
As an example, I'll use what fusion::less actually does. (It doesn't quite do a lexicographical comparison. It truncates to the length of the shorter sequence.) This may be slightly contrived, but I'm sure you'll agree that there exist algorithms with identical requirements, neither one of which can be easily implemented in terms of the other.
Granted. Okay, so that would be template <FusionSequence S1, FusionSequence S2> requires LessThanComparable<S1,S2> bool what_fusion_less_actually_does(S1 const& x, S2 const& y) { ... } Right? Same requirements.
Now, suppose that I want to write a function template<FusionSequence S1, FusionSequence S2> void foo(S1, S2); which calls both of these algorithms. How can I write the requirements for foo?
template <FusionSequence S1, FusionSequence S2> requires LessThanComparable<S1,S2> bool foo(S1 const& x, S2 const& y) { return less(x,y) && what_fusion_less_actually_does(x,y); }
a) requires LessThanComparable<S1, S2> && TruncatingLessThanComparable<S1, S2> Is every function template that calls foo also going to have to list both of these? This is silly and makes foo difficult to change, because the concept requirements include extraneous information. Remember that the two sets of types that model these concepts are the same. b) Leave it with just FusionSequence. I hope this won't compile unless you have a concept_map LessThanComparable<FusionSequence, FusionSequence> which is a bad idea, as I explained above. c) Somehow define a concept that allows both LessThanComparable and TruncatingLessThanComparable to be deduced. This would be ideal, but I don't have the least idea how to accomplish it. d) Something else I haven't thought of?
I don't understand why you'd go down any of those roads. Am I missing something? -- Dave Abrahams BoostPro Computing http://www.boostpro.com