Search code examples
c++structmetaprogrammingboost-fusion

How to check if a boost fusion sequence is an adapted struct?


Is there a trait or meta function or anything to check at compile time if a sequence is actually an adapted struct, so that I could e.g. get its member names? I saw people doing that by exclusion, something along the lines of “if it’s not a vector but it’s still a sequence, then it must be a struct” (I am making up because I don’t remember precisely). I didn’t think it’s a sufficient condition, there probably should be something better in fusion to achieve that. Couldn’t find it though. Please share if you know. Thanks.


Solution

  • I don't know if there is a better way, but you can use:

    template <typename T>
    using is_adapted_struct=std::is_same<typename boost::fusion::traits::tag_of<T>::type,boost::fusion::struct_tag>;
    

    This will work with structs adapted with BOOST_FUSION_ADAPT_STRUCT or defined with BOOST_FUSION_DEFINE_STRUCT and I believe also their named and templated variations (but not with the BOOST_FUSION_ADAPT_ASSOC_STRUCT and its variations (you would need to replace struct_tag with assoc_struct_tag for it to work)). I think (and this might be a problem for your use case) that this will also return true for classes adapted with BOOST_FUSION_ADAPT_ADT.

    Example on Wandbox

    #include <iostream>
    #include <type_traits>
    #include <boost/fusion/include/tag_of.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    #include <boost/fusion/include/vector.hpp>
    
    struct adapted
    {
        int foo;
        double bar;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(adapted, foo, bar);
    
    struct not_adapted{};
    
    
    template <typename T>
    using is_adapted_struct=std::is_same<typename boost::fusion::traits::tag_of<T>::type,boost::fusion::struct_tag>;
    
    
    
    int main()
    {
        static_assert(is_adapted_struct<adapted>::value);
        static_assert(!is_adapted_struct<not_adapted>::value);
        static_assert(!is_adapted_struct<boost::fusion::vector<int,double>>::value);
    }