Search code examples
c++templatesboostmetaprogrammingboost-proto

Can I know the type of what matched boost::proto::_ in a transform?


In the boost::proto manual, there is an example of a grammar that matches terminals of type std::transform<...>:

struct StdComplex
  : proto::terminal< std::complex< proto::_ > >  
{};

I would like to write a transform that does something with the type of the proto::_. For example, when matching a proto::terminal< std::complex< T > >, it returns a boost::shared_ptr < T > .

Is this possible?

Another way to state my question is, how do I make the following snippet work?

template<typename T>
struct Show : proto::callable  
{
    typedef T result_type;

    result_type operator()(T& v)
    {
        std::cout << "value = " << v << std::endl;
        return v;
    }
};


struct my_grammar
: proto::when<proto::terminal<proto::_ >, Show<??? what comes here ???>(proto::_value) >  
{};  

Solution

  • Your Show transform will be easier to handle as a Polymorphic Function Object :

    struct Show : proto::callable  
    {
      template<class Sig> struct result;
    
      template<class This, class T>
      struct result<This(T)>
      {
        typedef T type;
      };
    
      template<class T> T operator()(T const& v) const
      {
          std::cout << "value = " << v << std::endl;
          return v;
      }
    };   
    
    struct my_grammar
    : proto::when<proto::terminal<proto::_ >, Show(proto::_value) >  
    {};  
    

    Your answer on the other problem is :

    struct to_shared : proto::callable  
    {
      template<class Sig> struct result;
    
      template<class This, class T>
      struct result<This(T)>
      {
        typedef typename T::value_type base;
        typedef shared_ptr<base> type;
      };
    
      template<class T> 
      typename result<to_share(T)>::type operator()(T const& v) const
      {
        // stuff
      }
    };
    
    
    struct my_grammar
    : proto::when<proto::terminal<complex<proto::_> >, to_shared(proto::_value) >  
    {};