[Proto] Errors due to narrowing conversions in matches.hpp

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. Specifically, the narrowing conversions occur at Line 354 and 363 in boost/proto/matches.hpp. They can be simply resolved using `static_cast<bool>(...)`. Regards, Michel

Peter, can you comment? On 4/21/2012 1:14 PM, Michel Morin 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.
Specifically, the narrowing conversions occur at Line 354 and 363 in boost/proto/matches.hpp. They can be simply resolved using `static_cast<bool>(...)`.
I can certainly add the static_cast, but it looks like this may in fact be a "bug" in boost::is_placeholder, which is defined as: template< class T > struct is_placeholder { enum _vt { value = 0 }; }; 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); }; Peter, do you prefer one or the other, or is there some reason you'd like to stick with the original formulation? -- Eric Niebler BoostPro Computing http://www.boostpro.com

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.
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. Regards, Michel

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
participants (2)
-
Eric Niebler
-
Michel Morin