[type_traits] superfluous add_pointer in function_traits or something else?

Hello! I'm trying to use function_traits but it fails to compile. It seems like the add_pointer is somehow related to the error, as using the helper struct directly (and thus avoiding add_pointer on supplied type) compiles ok. I'm using boost 1.30.2 with g++ 3.2.2 on linux. The minimal example is: #include <boost/type_traits/function_traits.hpp> int foo() {} template<typename T> void bar(T f) { typedef typename boost::function_traits<T>::result_type X; //fails to compile typedef typename boost::detail::function_traits_helper<T>::result_type Y; //OK } int main(int argc, char** argv) { bar(foo); } The compiler output is: $ g++ func_traits.cpp func_traits.cpp: In instantiation of `boost::function_traits<int (*)()>': func_traits.cpp:7: instantiated from `void bar(T) [with T = int (*)()]' func_traits.cpp:13: instantiated from here func_traits.cpp:7: base class `boost::detail::function_traits_helper<int (**)()>' has incomplete type func_traits.cpp: In function `void bar(T) [with T = int (*)()]': func_traits.cpp:13: instantiated from here func_traits.cpp:7: no type named `result_type' in `struct boost::function_traits<int (*)()>' Is I'm using function_traits wrong or there is something wrong with the implementation? And another small thing that looks a bit strange to me: for some reason boost/type_traits.hpp does not link boost/type_traits/function_traits.hpp, but it never mentioned in documentation. -- Best regards, Zigmar

Pavel Antokolsky aka Zigmar wrote:
Hello! I'm trying to use function_traits but it fails to compile. It seems like the add_pointer is somehow related to the error, as using the helper struct directly (and thus avoiding add_pointer on supplied type) compiles ok. I'm using boost 1.30.2 with g++ 3.2.2 on linux.
The minimal example is: #include <boost/type_traits/function_traits.hpp>
int foo() {}
template<typename T> void bar(T f) { typedef typename boost::function_traits<T>::result_type X; //fails to compile typedef typename boost::detail::function_traits_helper<T>::result_type Y; //OK
}
int main(int argc, char** argv) { bar(foo); }
First of all, you really shouldn't be using anything in 'detail' namespaces -- what's in there are implementation details which a) might be removed at any time b) might be changed to behave differently at any time c) might even be defined differently or not at all for some compilers. 'T' is deduced to a function /pointer/. You have to use the plain function type (without the pointer on top) for 'function_traits' to work: typedef typename boost::function_traits< typename boost::remove_pointer<T>::type >::result_type X; Note that 'function_traits' won't work with function objects (that is clases with an overloaded operator()). Guessing from the code you posted you might be better off using Boost.ResultOf: http://www.boost.org/libs/utility/utility.htm#result_of Further, a library that provides a more complete set of traits classes entirely dedicated to built-in functional types (and pointers/references thereof) has been accepted into Boost, recently. It's not in the CVS yet and can be downloaded from the Boost file vault: http://tinyurl.com/qaf5f - zip archive Regards, Tobias

Hi, Tobias. Thanks for your answer On 1/24/07, Tobias Schwinger <tschwinger@isonews2.com> wrote:
First of all, you really shouldn't be using anything in 'detail' namespaces -- what's in there are implementation details which a) might be removed at any time b) might be changed to behave differently at any time c) might even be defined differently or not at all for some compilers. Sure, I know. I didn't use it in production of course, but I played with it trying to pin down the problem.
'T' is deduced to a function /pointer/. You have to use the plain function type (without the pointer on top) for 'function_traits' to work:
typedef typename boost::function_traits< typename boost::remove_pointer<T>::type >::result_type X; Ah, thanks. That what I've been missing. I can of course "remove_pointer", but what I'm wandering, is why the function_traits tries to add pointer in a first place? Besides, it seems relatively easy to detect if type is pointer or not, and make function_traits to work with both...
Note that 'function_traits' won't work with function objects (that is clases with an overloaded operator()). Guessing from the code you posted you might be better off using Boost.ResultOf:
http://www.boost.org/libs/utility/utility.htm#result_of Thanks. It looks like nice solution, but unfortunately it is not available in the boost version I'm using (1.30).
Further, a library that provides a more complete set of traits classes entirely dedicated to built-in functional types (and pointers/references thereof) has been accepted into Boost, recently. Thats a cool library, I agree. But again, it is not currently available in my version, and it would be overkill in terms of management to introduce a library that is not currently part of the boost for relatively simple functionality I need.
-- Best regards, Zigmar

Pavel Antokolsky aka Zigmar wrote:
'T' is deduced to a function /pointer/. You have to use the plain function type (without the pointer on top) for 'function_traits' to work:
typedef typename boost::function_traits< typename boost::remove_pointer<T>::type >::result_type X; Ah, thanks. That what I've been missing. I can of course "remove_pointer", but what I'm wandering, is why the function_traits tries to add pointer in a first place?
It's done to please broken compilers, I guess. Further, usually you want to accept both function objects and function pointers: template<typename R, typename F> void foo_impl(F f); template<class F> inline void foo(F f) { typedef typename F::result_type result; foo_impl<result>(f); } template<typename F> inline void foo(F * f) { typedef typename boost::function_traits<F>::result_type result; foo_impl<result>(f); } And if done like this, the function type is deduced without a pointer. Regards, Tobias
participants (2)
-
Pavel Antokolsky aka Zigmar
-
Tobias Schwinger