c++boosttype-erasureany

Create a `boost::any_collection` with a custom concept


I want to create a boost::any_collection of entities that satisfies a custom concept of mine:

#include <Command>

template<typename T>
concept ModelConcept = [] {

  return requires (T model) {
    { model.setCommand(Command{}) } -> std::same_as<void>;
  };
  }();

I've tried different timew but with no success:

boost::any_collection<ModelConcept> entities;

template <ModelConcept T>
struct ModelConceptWrapper {
  T obj;
};

boost::any_collection<ModelConceptWrapper> entities2;

boost::any_collection<ModelConceptWrapper<>> entities2;

But with no success. I didn't find anything in the documentation that helps me, since it uses the streamable of type_erasure.

How can I create it?


Solution

  • Like the commenter said, you need a Boost Type-Erasure concept. E.g.:

    #include <boost/type_erasure/member.hpp>
    
    namespace mylib {
        struct Command {};
        BOOST_TYPE_ERASURE_MEMBER(hasSetCommandConcept, setCommand);
    }
    
    using hasSetCommand = mylib::hasSetCommandConcept<void(mylib::Command)>;
    

    Live Demo

    Live On Coliru

    // #include <Command>
    #include <boost/poly_collection/any_collection.hpp>
    #include <boost/type_erasure/member.hpp>
    #include <iostream>
    
    namespace mylib {
        struct Command {};
        BOOST_TYPE_ERASURE_MEMBER(hasSetCommandConcept, setCommand);
    }
    
    using hasSetCommand = mylib::hasSetCommandConcept<void(mylib::Command)>;
    
    struct Model1 {
        void setCommand(mylib::Command) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    };
    struct Model2 {
        void setCommand(mylib::Command) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    };
    
    int main() {
        boost::poly_collection::any_collection<hasSetCommand> collection;
    
        collection.insert(Model1{});
        collection.insert(Model2{});
        collection.insert(Model1{});
        collection.insert(Model1{});
    
        for (mylib::Command command; auto const& obj : collection)
            obj.setCommand(command);
    }
    

    Printing

    void Model2::setCommand(mylib::Command)
    void Model1::setCommand(mylib::Command)
    void Model1::setCommand(mylib::Command)
    void Model1::setCommand(mylib::Command)