Search code examples
c++boostc++14fusion

Initialise const fusion boost list from derived class


Is it possible to initialise a member fusion vector to a value specified in a derived class without making the base class a template class?

like this:

class container
{
const auto children;
container (auto children):children (children){}
}

class derived : public container
{
derived():container(make_vector(string("test1"),string("test"))){} // http://www.boost.org/doc/libs/1_57_0/libs/fusion/doc/html/fusion/container/generation/functions/make_vector.html
}

I know that will not work- but I hope it will make it easier to understand my goal.

  1. delaying the specification of the types the vector will contain until a class derives from it.
  2. Without specifying the types the vector should contain by making the base class a template class

If not- what is closest thing to it?


Solution

  • The closest thing that doesn't require the base class to be a template is to use type erasure. You can roll your own ¹ or use Boost Type Erasure etc. Pick what suits you best.

    The simplest way to achieve it would be boost::any:

    Sample

    Live On Coliru

    #include <boost/any.hpp>
    #include <boost/fusion/include/io.hpp>
    #include <boost/fusion/include/vector.hpp>
    #include <boost/fusion/include/make_vector.hpp>
    #include <string>
    
    namespace fus = boost::fusion;
    
    class container
    {
      protected:
        boost::any children;
    
        template <typename T>
        container (T const& children) : children(children) {}
    };
    
    class derived : public container
    {
        using V = boost::fusion::vector2<std::string, std::string>;
      public:
        derived() : 
            container(fus::make_vector(std::string("test1"),std::string("test"))){} 
    
        friend std::ostream& operator<<(std::ostream& os, derived const& d) {
            return os << boost::any_cast<V const&>(d.children);
        }
    };
    
    #include <iostream>
    
    int main() {
        derived d;
        std::cout << d;
    }
    

    Prints

    (test1 test)
    

    ¹ e.g.