Boost logo

Boost :

Subject: Re: [boost] disable_if conundrum
From: Marshall Clow (mclow.lists_at_[hidden])
Date: 2011-12-05 15:15:22


On Dec 5, 2011, at 11:39 AM, Jeffrey Lee Hellrung, Jr. wrote:

> On Mon, Dec 5, 2011 at 11:30 AM, Jeremiah Willcock <jewillco_at_[hidden]>wrote:
>
>> 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.

[ snip]

>>> I want to provide a range-based version of it.

[ snip ]

>>> 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

[ more snippage ]

>>> 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.
>>
>
> Just to supplement: also use an extra level of indirection, a metafunction
> that maps Range to the return type of foo. So will look like
> boost::lazy_disable_if_c< condition, foo_result< Range > >::type.
>

Yeah, that didn't seem to work for me.
So - here's some code.
And here's some error messages (from clang 3.0):

        $ clang++ -I /Volumes/EyeFive/Marshall/Sources/boost/trunk disable_if.cpp
        In file included from disable_if.cpp:5:
        In file included from /Volumes/EyeFive/Marshall/Sources/boost/trunk/boost/range/begin.hpp:24:
        In file included from /Volumes/EyeFive/Marshall/Sources/boost/trunk/boost/range/iterator.hpp:23:
        /Volumes/EyeFive/Marshall/Sources/boost/trunk/boost/mpl/eval_if.hpp:60:26: error: no type named
                  'type' in 'boost::range_const_iterator<__gnu_cxx::__normal_iterator<int *, std::vector<int,
                  std::allocator<int> > > >'
                typedef typename f_::type type;
                                ~~~~~~~~~~~~~^~~~
        /Volumes/EyeFive/Marshall/Sources/boost/trunk/boost/range/iterator.hpp:61:18: note: in instantiation
                  of template class 'boost::mpl::eval_if_c<true,
                  boost::range_const_iterator<__gnu_cxx::__normal_iterator<int *, std::vector<int,
                  std::allocator<int> > > >, boost::range_mutable_iterator<const
                  __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > > >' requested
                  here
                                mpl::eval_if_c< is_const<C>::value,
                                         ^
        disable_if.cpp:29:37: note: in instantiation of template class 'boost::range_iterator<const
                  __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > >' requested here
                                        typedef std::pair<typename boost::range_iterator<const Range>::type,
                                                                                                          ^
        disable_if.cpp:45:20: note: in instantiation of template class
                  'detail::range_pair<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> >
> >' requested here
                                        typename detail::range_pair<Range>::type>
                                                                         ^
        disable_if.cpp:47:1: note: while substituting deduced template arguments into function template
                  'Foo' [with Range = __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> >
>, Compare = ]
        Foo ( const Range &r, Compare comp )
        ^
        disable_if.cpp:83:2: note: in instantiation of function template specialization
                  'test_sequence_no_comparison<std::vector<int, std::allocator<int> > >' requested here
                        test_sequence_no_comparison ( v ); // even # of elements
                        ^
        1 error generated.

Thanks!

-- Marshall

Marshall Clow Idio Software <mailto:mclow.lists_at_[hidden]>

A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait).
        -- Yu Suzuki




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