Search code examples
c++boosttype-traitsboost-proto

Obtaining the tag type of a Boost Proto child expression


Of a Boost Proto expression, when should I not expect a proto_tag member? I can enquire regarding the tag type of a placeholder, say, using either of the following methods:

typedef proto::tag_of<decltype(_1)>::type ta;
typedef decltype(_1)::proto_tag           tb;

But if I ask about the tag type of an expression's child, it appears that the proto_tag member is absent; and the third line of the following code gives an error:

auto f = _1 + _2;
typedef proto::tag_of<decltype(proto::child_c<0>(f))>::type tc;
typedef decltype(proto::child_c<0>(f))::proto_tag           td; // error

Clang and GCC's errors report that the type in question: is not a class, namespace, or scoped enumeration. I use Clang 3.2, GCC 4.7.2, and Boost 1.53.


Solution

  • The error that g++ 4.8.0 gives is basically:

    decltype evaluates to phx::actor<proto::expression>&, which is not a class or enumeration type

    In order to use :: you need to have an unqualified type so you must remove the reference:

    #include <type_traits>
    typedef std::remove_reference<decltype(proto::child_c<0>(f))>::type::proto_tag td;
    

    I believe you could also use:

    typedef proto::result_of::child_c<decltype(f),0>::type::proto_tag td;
    

    Using proto::tag_of you don't need to worry about the possible reference since it is removed when it's necessary:

    template<typename Expr>
    struct tag_of
    {
        typedef typename Expr::proto_tag type;
    };
    
    template<typename Expr>
    struct tag_of<Expr &>
    {
        typedef typename Expr::proto_tag type;
    };