Hi,
I have code similar to the following snippet:
#include <boost/fusion/container/list/list.hpp> #include <boost/fusion/container/list/convert.hpp> #include <boost/fusion/container/generation/make_list.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> namespace fusion=boost::fusion;
template<typename T> class A { public: struct B {};
B make_b() const { return B(); } };
template<typename T> A<T> make_a( T const& ) { return A<T>(); }
struct make_b { template<typename Sig> struct result;
template <typename DS> struct result<make_b(DS const&)> { typedef typename DS::B type; };
template <typename T> typename T::B operator()(T const& t) const { return t.make_b(); } };
int main() { namespace fusion=boost::fusion;
fusion::as_list( fusion::transform( fusion::make_list( make_a( 1. ), make_a( 1 ) ), make_b() ) );
return 0; }
it fails to compile with an error like this:
... rather long context here ..\..\../boost/utility/result_of.hpp:83:1: error: invalid use of incomplete type ‘struct make_b::result<make_b(A<double>)>’ test.cpp:27:35: error: declaration of ‘struct make_b::result<make_b(A<double>)>’
What am I doing wrong?
You need to add a specialization result_of<make_b(DS)>, in addition to result_of<make_b(DS const&)>: template <typename DS> struct result<make_b(DS)> { typedef typename DS::B type; }; You need this because your operator() can be called with either a argument of type T, or an argument of type T const&. You don't need two versions of your operator(), because T is implicitly convertible to T const&, but the result<> template is instantiated with the exact argument type without any conversions being performed. This is subtle issue, I explain it in more detail here [1]. Thank goodness in C++11 we will be able to avoid it by using decltype. Regards, Nate [1] http://lists.boost.org/boost-users/2011/07/69684.php