[type_traits][result_of] Handling of cv-qualified function pointers/references

Hi! While fixing some issues with fusion::unpack_args I noticed that cv-qualified function pointers are not handled by result_of and type_traits::is_function doesn't handle cv-qualified functions. Here's a simple test case for result_of: #include <boost/utility/result_of.hpp> typedef int (* const c_func_ptr)(int); typedef boost::result_of<c_func_ptr(int)>::type return_type; and a slightly more convoluted for type_traits::is_pointer: #include <boost/type_traits/is_function.hpp> #include <boost/static_assert.hpp> void foo (); template <class F> void bar(F &) { BOOST_STATIC_ASSERT(boost::is_function<F const>::value); } template <class F> void baz(F const & f) { bar(f); } int main() { baz(foo); } Both failing with gcc-4.x. The first test case also fails with gcc-3.2.3. while the second case fails for a completely different reason in overload resolution. For unpack_args I worked around these issues by applying remove_cv to pointers in general and also before testing with is_function. In either case cv-qualification shouldn't affect the type of the arguments or the result, which is what I'm interested in. Anyway I'm thinking that the solution could be moved upstream so others won't stumble upon the same issues. Thoughts? Best regards, João

João Abecasis wrote:
and a slightly more convoluted for type_traits::is_pointer:
#include <boost/type_traits/is_function.hpp> #include <boost/static_assert.hpp>
void foo ();
template <class F> void bar(F &) { BOOST_STATIC_ASSERT(boost::is_function<F const>::value); }
template <class F> void baz(F const & f) { bar(f); }
int main() { baz(foo); }
Right that should fail because: *There is no such thing as a const-qualified function type in the C++ language* So argument deduction for baz would fail because it would have an invalid signature. Actually, having said that, I seem to remember that behaviour may have been changed by a DR that makes a cv-qualified function type (or reference) the same as the non-cv-qualified type. Unfortunately this is a bug that crops up in compilers from time to time, often they allow you to generate cv-qualified function or reference types inadvertently, but don't let you test for them with partial specialistion because that part of the compiler "knows" the situation can never occur :-( BTW your code compiles cleanly with gcc-3.4.4 and Intel 9 and VC++8 (after removing the const from the function baz). I'm surprised that gcc-4 has this issue, I'm fairly sure we looked at this for gcc-2 and couldn't fix it (or maybe it was the cv-qualified reference issue we looked at, I don't remember now). Whatever, if you have a patch that works then yes lets fix is_function to workaround the problem for those specific compilers. John.
Both failing with gcc-4.x. The first test case also fails with gcc-3.2.3. while the second case fails for a completely different reason in overload resolution.
For unpack_args I worked around these issues by applying remove_cv to pointers in general and also before testing with is_function. In either case cv-qualification shouldn't affect the type of the arguments or the result, which is what I'm interested in.
Anyway I'm thinking that the solution could be moved upstream so others won't stumble upon the same issues. Thoughts?
Best regards,
João
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hi! John Maddock wrote:
João Abecasis wrote:
and a slightly more convoluted for type_traits::is_pointer:
#include <boost/type_traits/is_function.hpp> #include <boost/static_assert.hpp>
void foo ();
template <class F> void bar(F &) {
This,
BOOST_STATIC_ASSERT(boost::is_function<F const>::value);
should actually be, BOOST_STATIC_ASSERT(boost::is_function<F>::value); Which means that the const function type is entirely synthesized by the compiler.
}
template <class F> void baz(F const & f) { bar(f); }
int main() { baz(foo); }
Right that should fail because:
*There is no such thing as a const-qualified function type in the C++ language*
Should this be reported as a bug in gcc 4, then?
So argument deduction for baz would fail because it would have an invalid signature. Actually, having said that, I seem to remember that behaviour may have been changed by a DR that makes a cv-qualified function type (or reference) the same as the non-cv-qualified type.
I do get the argument deduction failure in baz with gcc-3.2.3 (from FC5). While vanilla gcc-4.0.3 and 4.1.0 result in a static assertion failure.
Unfortunately this is a bug that crops up in compilers from time to time, often they allow you to generate cv-qualified function or reference types inadvertently, but don't let you test for them with partial specialistion because that part of the compiler "knows" the situation can never occur :-(
BTW your code compiles cleanly with gcc-3.4.4 and Intel 9 and VC++8 (after removing the const from the function baz).
That const is the fundamental one. The other one appeared from the lack of synchronization of the report with the actual test case... (Now I need literate programming in my e-mails too! :-) )
I'm surprised that gcc-4 has this issue, I'm fairly sure we looked at this for gcc-2 and couldn't fix it (or maybe it was the cv-qualified reference issue we looked at, I don't remember now). Whatever, if you have a patch that works then yes lets fix is_function to workaround the problem for those specific compilers.
The way I "solved" this for unpack_args was to apply remove_cv to the type before testing with is_pointer. We don't need to know if it is a cv-qualified function beforehand. Perhaps the same approach could be used in type_traits: template <class T> struct is_pointer : is_pointer_impl<typename remove_cv<T>::type> { }; ? Admittedly this would only be enabled if and where it makes a difference. Best regards, João
participants (2)
-
John Maddock
-
João Abecasis