Boost logo

Boost :

Subject: Re: [boost] [Proto] Errors due to narrowing conversions in matches.hpp
From: Eric Niebler (eric_at_[hidden])
Date: 2012-04-22 02:29:06


On 4/21/2012 10:22 PM, Michel Morin wrote:
> Eric Niebler wrote:
>>> Some tests of Boost.Phoenix fail on clang trunk in a C++11 mode
>>> due to narrowing conversions of non-type template arguments,
>>> which are prohibited in C++11.
>>
>> Really?! Wow, that's a breaking change I hadn't heard of before.
>
> Let me elaborate a bit.
> On clang-cxx11-r155296 test runner,
> ( http://www.boost.org/development/tests/trunk/developer/phoenix.html )
> there are many failures due to the following errors.
>
> boost/proto/matches.hpp:354:17:
> error: non-type template argument evaluates to 2,
> which cannot be narrowed to type 'bool' [-Wc++11-narrowing]
>
> boost/proto/matches.hpp:363:21:
> error: non-type template argument evaluates to 2,
> which cannot be narrowed to type 'bool' [-Wc++11-narrowing]
>
> The problem is that
> remove_reference<
> typename when<_, If>::template impl<Expr, int, int>::result_type
> >::type::value
> evaluates to "2", which is not in the range of bool.
> This causes the compiler errors.

I'm trying to understand why it doesn't evaluate to a bool, because it
should. The fact that it doesn't may indicate a bug in Phoenix or some
other library. Since I have never been able to get clang to work on
Windows (hello, clang team!), I had to resort to eyeballing Phoenix,
which let me to the oddness in is_placeholder.

>> Ideally, this should be a valid MPL Integral Constant of type bool, like:
>>
>> template< class T >
>> struct is_placeholder
>> : mpl::false_
>> {};
>>
>> If that is not portable enough, it could be:
>>
>> template< class T > struct is_placeholder
>> {
>> BOOST_STATIC_CONSTANT(bool, value = false);
>> };
>
> Neither of them solve the problem.
> After applying the proposed change, we still have the same errors.

I looked a bit deeper and found the problem in boost/bind/arg.hpp.
There, is_placeholder is specialized for arg<I> to have a value of I,
the placeholder number. Despite its name, is_placeholder is *not* a
boolean metafunction! C++11 defines std::is_placeholder similarly. It's
a naming issue. Bizarre. <Thinking...> Adding the static_cast like you
suggest is probably the right fix.

Btw, many thanks for helping to flush out and track down these problems.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

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