Boost logo

Boost :

Subject: Re: [boost] [guidelines] why template errors suck
From: Jeremiah Willcock (jewillco_at_[hidden])
Date: 2010-09-28 11:21:55

On Tue, 28 Sep 2010, Andrew Sutton wrote:

> On Tue, Sep 28, 2010 at 9:20 AM, David Abrahams <dave_at_[hidden]> wrote:
>> At Tue, 28 Sep 2010 08:39:23 -0500,
>> Andrew Sutton wrote:
>>> Having done the exercise, I'm satisfied with my results (which agree with
>>> Mathias').
>> Great; let's see your work!
> This is my interpretation of the type constraints on the template parameters
> of the find_if algorithm.
> template<typename Iter, typename Pred>
> Iter find_if(Iter f, Iter l, Pred p)
> {
> for( ; f != l; ++f) if(p(*f)) return f;
> return l;
> }
> Expressions on Iter:
> f != l;
> *f;
> ++f;
> Expressions on pred:
> p(*f)
> and...
> is_convertible<decltype(f != l), bool>::value
> is_convertible<decltype(p(*f)), bool>::value

These can be written as "normal" valid expressions:

bool(f != l)

> I don't know if you'd count the last two as "valid expressions", but they
> clearly seem to be requirements on the algorithm. I'm probably missing copy
> constructibility requirements.

Just to show the subtletly of using valid expressions, the p(*f)
constraint (with or without a conversion on the outside) would not allow
the following:

struct p {
   template <typename T>
   bool operator()(T) const { /* Something invalid */ }

   bool operator()(bool) const {return true;}

vector<bool> v;
find_if(v.begin(), v.end(), p());

(note that the wrong operator()() will be chosen for the
*vector<bool>::iterator proxy).

> It's hard to provide an argument more concrete than an example that
>> doesn't work. But in fairness I guess it's also easy to overlook
>> non-workingness when you don't have a computer doing the checking for
>> you, or the STL wouldn't have been designed with the "valid
>> expression" approach...
>> OK, I found a good explanation. See §3.2.3 of
> That is a good explanation, but I don't see why type traits can't be used to
> enforce convertability or same-type requirements. Why not describe
> LessThanComparable as?
> static_assert(is_same<decltype(x < y), bool>::value, "")
> Besides the fact that it's a little gross. We can do this now (with C++0x
> anyway), and we do use is_same<> to constrain key/value types in
> SimpleAssociativeContainers.
> It seems to me that writing constraints in terms of valid expressions gives
> you flexibility when you want it, but doesn't preclude the strengthening of
> requirements when needed.

The issue is that convertability constraints are too easy to get wrong
(within algorithms); see p. 8 of N1758 that was linked to before. You can
write them without is_convertible (as they were done before). Using
is_same<decltype(...), ...> is fine, but that might cause trouble for
users since now they can't return proxies (or even references) as their
function results. A pseudosignature-based approach allows conversions
both on the user side and the algorithm side without any of the gyrations
and subtlety that shows up with valid expressions.

-- Jeremiah Willcock

Boost list run by bdawes at, gregod at, cpdaniel at, john at