Boost logo

Boost :

Subject: Re: [boost] disable_if conundrum
From: Jeremiah Willcock (jewillco_at_[hidden])
Date: 2011-12-05 14:30:30


On Mon, 5 Dec 2011, Marshall Clow wrote:

> I have a function that returns a pair of iterators.
> There's also a version that takes a comparison predicate.
>
> template<class ForwardIterator, class Compare>
> std::pair<ForwardIterator, ForwardIterator>
> foo ( ForwardIterator first, ForwardIterator last );
>
> template<class ForwardIterator, class Compare>
> std::pair<ForwardIterator, ForwardIterator>
> foo ( ForwardIterator first, ForwardIterator last, Compare comp );
>
>
> I want to provide a range-based version of it.
>
> template<class Range>
> std::pair<typename boost::range_iterator<const Range>::type, typename boost::range_iterator<const Range>::type>
> foo ( const Range &r );
>
> template<class Range, class Compare>
> std::pair<typename boost::range_iterator<const Range>::type, typename boost::range_iterator<const Range>::type>
> foo ( const Range &r, Compare comp );
>
> Ok. There's a problem.
> If I call:
> foo ( first, last )
> I get an error, because there are two perfectly good two argument candidates.
>
> Fine. Been there, seen that. I can use disable_if to make sure that the second range based version is only "active" when the arguments are different types. It's verbose, but it (usually) works
>
> template<class Range, class Compare>
> typename boost::disable_if_c<boost::is_same<Range, Compare>::value,
> std::pair<typename boost::range_iterator<const Range>::type, typename boost::range_iterator<const Range>::type>
> >::type
> foo ( const Range &r, Compare comp );
>
> But this time it does not! I get a compile error telling me that the compiler can't deal with boost::range_iterator<XXX>::type, when XXX = some random iterator. It seems that the compiler wants to evaluate all the parameters of disable_if_c before deciding whether or not to SFINAE it (I guess that's not unreasonable, but it's not what I want)
>
> Apparently, all the other times that I did this, the return type of the function was not a dependent type of the template arguments.
>
> Any suggestions for a workaround here?

Look at lazy_disable_if -- it doesn't get the nested "type" member of the
type you give it unless the condition evaluates to false.

-- Jeremiah Willcock


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk