Search code examples
c++templatesboosttemplate-meta-programmingboost-mpl

How am I supposed to write a metafunction that works like the ones in MPL?


I seem to be missing something when trying to write a meta-function that calls into MPL code. The follow code fails to compile with the following error on inst2, but works fine on inst1:

error C2903: 'apply' : symbol is neither a class template nor a function template

using namespace boost::mpl;

template <typename VECTOR>
struct first_element : mpl::at_c<VECTOR, 0> {};

int main()
{
    typedef vector<
        vector<int, int>,
        vector<int, int>,
        vector<int, int>> lotso;

    typedef mpl::transform<lotso,
        first_element<_1>>::type inst1;

    typedef first_element<
        at_c<lotso,0>>::type inst2;

    return 0;
}

Solution

  • I think you forgot a ::type behind the call to at_c inside the typedef for inst2. Recall that your first_element expects something on which at_c can be applied. The raw at_c<lotso, 0>, however, is not yet evaluated. Evaluating a metafunction is done by adding ::type.

    #include <boost/mpl/vector.hpp>
    #include <boost/mpl/at.hpp>
    #include <boost/mpl/transform.hpp>
    #include <boost/mpl/placeholders.hpp>
    #include <type_traits>
    
    using namespace boost;
    using namespace boost::mpl;
    
    template <typename VECTOR>
    struct first_element : mpl::at_c<VECTOR, 0> {};
    
    int main()
    {
        typedef vector<
            vector<int, int>,
            vector<int, int>,
            vector<int, int>> lotso;
    
        typedef mpl::transform<lotso,
            first_element<_1>>::type inst1;
    
        typedef first_element<
            at_c<lotso,0>::type >::type inst2;
                         ^^^^^^ <--- you forgot a ::type here
    
        static_assert(std::is_same<first_element<inst1>::type, inst2>::value, "bingo");
    
        return 0;
    }
    

    Live Example. As a further check, I verified that a further dereference on inst1 gives the same type as inst2.