[boost][proto] Type inference using transform

I am trying to decide whether the argument type to a function taking a proto expression should be "const T&" or "T&" based on the expression itself. Suppose the expression was "_1 = _2 + 1" I want the first argument to a function, say FOO, to be T& and second argument to be const T&. I write a transform argtype<int, typename> as follows : #include <boost/proto/proto.hpp> #include <boost/mpl/int.hpp> #include <iostream> struct arg_tag {}; namespace proto = boost::proto; namespace mpl = boost::mpl; using namespace std; template<int N> struct arg : proto::or_<proto::nullary_expr<arg_tag, mpl::int_<N> > > {}; template<typename T> struct readonly : proto::callable { template<typename Sig> struct result; template<typename This> struct result<This()> { typedef const T& type; }; }; template<typename T> struct readwrite : proto::callable { template<typename Sig> struct result; template<typename This> struct result<This()> { typedef T& type; }; }; template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite<T>()> , proto::otherwise<readonly<T>()>
{}; proto::nullary_expr<arg_tag, mpl::int_<0> >::type const _1 = {{}}; proto::nullary_expr<arg_tag, mpl::int_<1> >::type const _2 = {{}}; template<typename E> void foo(const E &e) { cout << typeid(typename boost::result_of<argtype<0,int>(const E&)>::type).name() << "\n"; } int main() { foo(_1=_1+1); return 0; } I expected the typeid printed out by the foo function to be equivalent to "int&" whereas I get "readwrite<int>". Any clues on where I am going wrong? Thanks, Manjunath http://nonchalantlytyped.net/blog/musings/

Manjunath Kudlur wrote:
I expected the typeid printed out by the foo function to be equivalent to "int&" whereas I get "readwrite<int>". Any clues on where I am going wrong?
Because that exactly what you ask in argtype ;) What you are missing is the fact that you readonly/readwrite function object are templated and proto can't know they are callable without a small help. So you need to add: namspace boost { namespace proto { template<class T> struct is_callable< readonly<T> > : mpl::true_ {}; template<class T> struct is_callable< readwrite<T> > : mpl::true_ {}; } } As stated in the doc, template trasnform don't trigger the callable stuff automatically -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

Moreover, your result are wrong result_of<T()> will always return void. You need somethign like: struct arg_tag {}; namespace proto = boost::proto; namespace mpl = boost::mpl; using namespace std; template<int N> struct arg : proto::or_<proto::nullary_expr<arg_tag, mpl::int_<N> > > {}; template<typename T> struct readonly : proto::callable { template<typename Sig> struct result; template<typename This,class X> struct result<This(X)> { typedef const T& type; }; }; template<typename T> struct readwrite : proto::callable { template<typename Sig> struct result; template<typename This,class X> struct result<This(X)> { typedef T& type; }; }; template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite<T>(proto::_)> , proto::otherwise<readonly<T>(proto::_)>
{}; proto::nullary_expr<arg_tag, mpl::int_<0> >::type const _1 = {{}}; proto::nullary_expr<arg_tag, mpl::int_<1> >::type const _2 = {{}}; namespace boost { namespace proto { template<class T> struct is_callable<readwrite<T> > : true_ {}; template<class T> struct is_callable<readonly<T> > : true_ {}; }}

On Thu, May 6, 2010 at 2:13 AM, joel falcou <joel.falcou@lri.fr> wrote:
Moreover, your result are wrong
result_of<T()> will always return void.
You need somethign like:
Thanks, Joel. (Note to self : RTFM more often :)). I also discovered that I didn't have to make the readonly and readwrite classes templated. The following also works : struct readonly : proto::callable { template<typename Sig> struct result; template<typename This, typename T> struct result<This(T)> { typedef const T& type; }; }; struct readwrite : proto::callable { template<typename Sig> struct result; template<typename This, typename T> struct result<This(T)> { typedef T& type; }; }; template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite(T())> , proto::otherwise<readonly(T())>
{}; Manjunath http://nonchalantlytyped.net/blog/musings/
struct arg_tag {};
namespace proto = boost::proto; namespace mpl = boost::mpl;
using namespace std;
template<int N> struct arg : proto::or_<proto::nullary_expr<arg_tag, mpl::int_<N> > > {};
template<typename T> struct readonly : proto::callable {
template<typename Sig> struct result;
template<typename This,class X> struct result<This(X)> { typedef const T& type; }; };
template<typename T> struct readwrite : proto::callable {
template<typename Sig> struct result;
template<typename This,class X> struct result<This(X)> { typedef T& type; }; };
template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite<T>(proto::_)> , proto::otherwise<readonly<T>(proto::_)>
{};
proto::nullary_expr<arg_tag, mpl::int_<0> >::type const _1 = {{}}; proto::nullary_expr<arg_tag, mpl::int_<1> >::type const _2 = {{}};
namespace boost { namespace proto { template<class T> struct is_callable<readwrite<T> > : true_ {}; template<class T> struct is_callable<readonly<T> > : true_ {}; }}
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thanks, Joel. (Note to self : RTFM more often :)). I also discovered that I didn't have to make the readonly and readwrite classes templated. The following also works :
This is even simpler : template<typename T> struct readonly : proto::callable { typedef const T& result_type; }; template<typename T> struct readwrite : proto::callable { typedef T& result_type; }; template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite<T>()> , proto::otherwise<readonly<T>()>
{}; namespace boost { namespace proto { template<class T> struct is_callable< readonly<T> > : mpl::true_ {}; template<class T> struct is_callable< readwrite<T> > : mpl::true_ {}; } } Manjunath http://nonchalantlytyped.net/blog/musings/
struct readonly : proto::callable {
template<typename Sig> struct result;
template<typename This, typename T> struct result<This(T)> { typedef const T& type; }; };
struct readwrite : proto::callable {
template<typename Sig> struct result;
template<typename This, typename T> struct result<This(T)> { typedef T& type; }; };
template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite(T())> , proto::otherwise<readonly(T())>
{};
Manjunath http://nonchalantlytyped.net/blog/musings/
struct arg_tag {};
namespace proto = boost::proto; namespace mpl = boost::mpl;
using namespace std;
template<int N> struct arg : proto::or_<proto::nullary_expr<arg_tag, mpl::int_<N> > > {};
template<typename T> struct readonly : proto::callable {
template<typename Sig> struct result;
template<typename This,class X> struct result<This(X)> { typedef const T& type; }; };
template<typename T> struct readwrite : proto::callable {
template<typename Sig> struct result;
template<typename This,class X> struct result<This(X)> { typedef T& type; }; };
template<int N, typename T> struct argtype : proto::or_< proto::when<proto::assign<arg<N>, proto::_>, readwrite<T>(proto::_)> , proto::otherwise<readonly<T>(proto::_)>
{};
proto::nullary_expr<arg_tag, mpl::int_<0> >::type const _1 = {{}}; proto::nullary_expr<arg_tag, mpl::int_<1> >::type const _2 = {{}};
namespace boost { namespace proto { template<class T> struct is_callable<readwrite<T> > : true_ {}; template<class T> struct is_callable<readonly<T> > : true_ {}; }}
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 5/6/2010 11:09 AM, Manjunath Kudlur wrote:
Thanks, Joel. (Note to self : RTFM more often :)). I also discovered that I didn't have to make the readonly and readwrite classes templated. The following also works :
This is even simpler :
template<typename T> struct readonly : proto::callable { typedef const T& result_type; };
<snip> If you define it like this: template<typename T, typename Dummy = proto::callable> struct readonly : proto::callable { typedef const T& result_type; }; ... then you don't need this:
namespace boost { namespace proto { template<class T> struct is_callable< readonly<T> > : mpl::true_ {}; template<class T> struct is_callable< readwrite<T> > : mpl::true_ {}; } }
HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (3)
-
Eric Niebler
-
joel falcou
-
Manjunath Kudlur