Boost serialization - abstrakte Klasse "templates may not be virtual"



  • Hallo zusammen, das Problem "templates may not be virtual" ist schon bekannt aber das Problem zu lösen, hängt von der Situation ab. Weiß jemand, wie man dieses Problem im Sinne von boost::serialization lösen kann?

    Der Code:

    #include <armadillo>
    
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/assume_abstract.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/split_member.hpp>
    
    #include <fstream>
    #include <iostream>
    #include <memory>
    #include <sstream>
    #include <vector>
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract
    
    //Serialization for Armadillo Matrices------------------
    BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)
    namespace boost::serialization {
        template<class Archive>
        void save(Archive & ar, const arma::mat &t, unsigned int version) {
            ar << t.n_elem;
            auto data = t.colptr(0);
            for (size_t K = 0; K < t.n_elem; ++K)
                ar << data[K];
        }
    
        template<class Archive>
        void load(Archive & ar, arma::mat &t, unsigned int version) {
            size_t n_elem;
            ar >> n_elem;
            t.set_size(n_elem);
            t.zeros();
            auto data = t.colptr(0);
            for (size_t K = 0; K < n_elem; ++K)
                ar >> data[K];
        }
    } // boost::serialization
    
    class Car {
    public:
          virtual double getInfo() = 0;
    
    private:
       template <typename Archive> //wo das Problem liegt
       virtual void serialize(Archive& ar, unsigned int version) = 0;
    };
    
    class Porsche : public Car {
    public:
        double getInfo() override { return 1.1; }
        Porsche(std::string owner1, int hp1, arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            A = A1; 
            
            }
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & owner;
            ar & hp;
            ar & A;
        }
    
    
        std::string owner;
        int hp{};
        arma::mat A;
        private:
    };
    
    class Audi : public Car {
    public:
        double getInfo() override { return 2; }
        Audi(std::string owner1, int hp1, std::string second_owner1, std::string country1,  arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            second_owner = second_owner1; 
            country = country1;
            A = A1; 
            }
     
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & owner;
            ar & hp;
            ar & second_owner;
            ar & country;
            ar & A;
        }
    
    
        std::string owner;
        int hp{};
        std::string second_owner;
        std::string country;
        arma::mat A;
        private:
    };
    
    int main() {
       {
            std::unique_ptr<Car> audi = std::make_unique<Audi>("Wilma", 3, "Rene", "Argentina" ,arma::randu<arma::mat>(4,5));
            audi->getInfo();
    
            std::unique_ptr<Car> porsche = std::make_unique<Porsche>("Joe", 14, arma::randu<arma::mat>(6,5));
            porsche->getInfo();
    
            std::ofstream outputStream("bin.dat", std::ios::binary);
            boost::archive::binary_oarchive ss(outputStream);
            ss & *audi.get();
            ss & *porsche.get();
        }
    
        {
            std::unique_ptr<Audi> audi = std::make_unique<Audi>();
            std::unique_ptr<Porsche>porsche = std::make_unique<Porsche>();
    
            std::ifstream inputStream("bin.dat", std::ios::binary);
            boost::archive::binary_iarchive ss(inputStream);
            ss & *audi.get();
            ss & *porsche.get();
    
            std::cout << "audi: hp=" << audi->hp << "\n";
            std::cout << "porsche: hp=" << porsche->hp<< " owner=" << porsche->owner << " A=" << porsche->A <<"\n";
    
        }
    }
    
    

    Fehler:

    virt_funk_seri.cpp:46:4: error: templates may not be ‘virtual’
        virtual void serialize(Archive& ar, unsigned int version) = 0;
        ^~~~~~~
    virt_funk_seri.cpp:46:64: error: templates may not be ‘virtual’
        virtual void serialize(Archive& ar, unsigned int version) = 0;
                                                                    ^
    
    


  • Mach die Funktion nicht-virtuell und rufe (bei Bedarf) in den abgeleiteten Klassen base_object<Car>(*this)auf, s. Serialization of Class Hierarchy Objects.



  • Boost.Serialization "serialize" Funktionen müssen ja auch nicht virtual sein, Boost.Serialization macht das IIRC über RTTI. Dafür muss man in vielen Fällen dann sämtliche abgeleiteten Typen im Archiv "registrieren" bevor man anfängt zu serialisieren: https://www.boost.org/doc/libs/1_72_0/libs/serialization/doc/serialization.html#derivedpointers



  • Ich danke euch. Ich habe den Link von Th69 benutzt und das erste Beispiel hat geholfen. Der Code kompiliert jetzt aber ich kriege einen Fehler wenn ich ./a.out aufrufe. Der Fehler ist unten -- hat jemand eine Idee was das Problem ist?

    Der geänderte Code:

    #include <armadillo>
    
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/assume_abstract.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/split_member.hpp>
    
    #include <fstream>
    #include <iostream>
    #include <memory>
    #include <sstream>
    #include <vector>
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract
    
    //Serialization for Armadillo Matrices------------------
    BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)
    namespace boost::serialization {
        template<class Archive>
        void save(Archive & ar, const arma::mat &t, unsigned int version) {
            ar << t.n_elem;
            auto data = t.colptr(0);
            for (size_t K = 0; K < t.n_elem; ++K)
                ar << data[K];
        }
    
        template<class Archive>
        void load(Archive & ar, arma::mat &t, unsigned int version) {
            size_t n_elem;
            ar >> n_elem;
            t.set_size(n_elem);
            t.zeros();
            auto data = t.colptr(0);
            for (size_t K = 0; K < n_elem; ++K)
                ar >> data[K];
        }
    } // boost::serialization
    
    class Car {
    public:
          virtual double getInfo() = 0;
    
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int version) {};
    };
    
    class Porsche : public Car {
    public:
        double getInfo() override { return 1.1; }
        Porsche(std::string owner1, int hp1, arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            A = A1; 
            
            }
        std::string owner;
        int hp{};
        arma::mat A;
        Porsche() = default;
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & boost::serialization::base_object<Car>(*this); //https://theboostcpplibraries.com/boost.serialization-class-hierarchies
            ar & owner;
            ar & hp;
            ar & A;
        }    
    
        
    };
    
    class Audi : public Car {
    public:
        double getInfo() override { return 2; }
        Audi(std::string owner1, int hp1, std::string second_owner1, std::string country1,  arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            second_owner = second_owner1; 
            country = country1;
            A = A1; 
            }
        Audi() = default;
        void setVariables(std::string owner1, int hp1, std::string second_owner1, std::string country1,  arma::mat A1)
        {
            owner = owner1;
            hp = hp1;
            second_owner = second_owner1; 
            country = country1;
            A = A1;
        }
    
        std::string owner;
        int hp{};
        std::string second_owner;
        std::string country;
        arma::mat A;
    
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & boost::serialization::base_object<Car>(*this); //https://theboostcpplibraries.com/boost.serialization-class-hierarchies
            ar & owner;
            ar & hp;
            ar & second_owner;
            ar & country;
            ar & A;
        }
    
    };
    
    int main() {
       {
            std::unique_ptr<Car> audi = std::make_unique<Audi>("Wilma", 3, "Rene", "Argentina" ,arma::randu<arma::mat>(4,5));
            audi->getInfo();
    
            std::unique_ptr<Car> porsche = std::make_unique<Porsche>("Joe", 14, arma::randu<arma::mat>(6,5));
            porsche->getInfo();
    
            std::ofstream outputStream("bin.dat", std::ios::binary);
            boost::archive::binary_oarchive ss(outputStream);
            ss & *audi.get();
            ss & *porsche.get();
        }
    
        {
            std::unique_ptr<Audi> audi = std::make_unique<Audi>();
            std::unique_ptr<Porsche>porsche = std::make_unique<Porsche>();
    
            std::ifstream inputStream("bin.dat", std::ios::binary);
            boost::archive::binary_iarchive ss(inputStream);
            ss & *audi.get();
            ss & *porsche.get();
    
            std::cout << "audi: hp=" << audi->hp << "\n";
            std::cout << "porsche: hp=" << porsche->hp<< " owner=" << porsche->owner << " A=" << porsche->A <<"\n";
    
        }
    }
    
    

    Der Fehler nach ./a.out:

    terminate called after throwing an instance of 'boost::archive::archive_exception'
      what():  input stream error
    [1]    7685 abort      ./a.out
    
    


  • Naja den interessanten Code wo wirklich serialisiert wird zeigst du ja nicht her. Schade.



  • Doch. Der gesamte Code ist im ersten Beitrag. Ich habe nur den geänderten Code im zweiten Beitrag gepostet (also alles außer int main()). Aber ich habe jetzt alles im zweiten Beitrag hinzugefügt, falls es einfacher ist.



  • Naja du registrierst ja nirgends deine Klassen. Dann kann polymorphe Serialisierung natürlich auch nicht gehen - zumindest nicht mit Boost.Serialization.
    Steht ja alles in den von @Th69 und mir verlinkten Seiten.

    Weiters ist IMO was du mit ss & *audi.get(); machst Quatsch. Wenn du eh schon weisst dass es ein Audi ist, wozu dann der Zeiger? Und wenn du es nicht weisst, dann solltest du auch besser die Pointer serialisieren und nicht die Objekte direkt. Weil dir Boost.Serialization dann anhand der Daten im Archiv automatisch den passenden Typ erstellt.

    Deine Klassen registrieren musst du aber natürlich trotzdem. Entweder statich über BOOST_CLASS_EXPORT oder dynamisch über register_type.



  • Danke für die weitere Erklärung. Warum kann das Beispiel von Th69 (verlinkte Seite - erstes Beispiel) ohne das Registrieren gehen? Ich habe

    BOOST_CLASS_EXPORT(Audi)
    BOOST_CLASS_EXPORT(Porsche)
    

    zu dem Code hinzugefügt aber ich kriege einen ähnlichen Fehler:

    terminate called after throwing an instance of 'boost::archive::archive_exception'
      what():  input stream error
    [1]    8134 abort      ./a.out
    
    

    Und auch zu deinem Punkt bzgl ss & *audi.get(). Ich habe den Code ohne den Zeiger ausprobiert und ich bekomme diese Fehler:

    virt_funk_seri.cpp: In function ‘int main()’:
    virt_funk_seri.cpp:155:22: error: invalid initialization of non-const reference of type ‘Audi*&’ from an rvalue of type ‘std::unique_ptr<Audi, std::default_delete<Audi> >::pointer {aka Audi*}’
             ss & audi.get();
                  ~~~~~~~~^~
    In file included from /usr/include/boost/archive/detail/common_iarchive.hpp:23:0,
                     from /usr/include/boost/archive/basic_binary_iarchive.hpp:30,
                     from /usr/include/boost/archive/binary_iarchive_impl.hpp:21,
                     from /usr/include/boost/archive/binary_iarchive.hpp:20,
                     from virt_funk_seri.cpp:3:
    /usr/include/boost/archive/detail/interface_iarchive.hpp:74:15: note:   initializing argument 1 of ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = Audi*; Archive = boost::archive::binary_iarchive]’
         Archive & operator&(T & t){
                   ^~~~~~~~
    virt_funk_seri.cpp:156:25: error: invalid initialization of non-const reference of type ‘Porsche*&’ from an rvalue of type ‘std::unique_ptr<Porsche, std::default_delete<Porsche> >::pointer {aka Porsche*}’
             ss & porsche.get();
                  ~~~~~~~~~~~^~
    In file included from /usr/include/boost/archive/detail/common_iarchive.hpp:23:0,
                     from /usr/include/boost/archive/basic_binary_iarchive.hpp:30,
                     from /usr/include/boost/archive/binary_iarchive_impl.hpp:21,
                     from /usr/include/boost/archive/binary_iarchive.hpp:20,
                     from virt_funk_seri.cpp:3:
    /usr/include/boost/archive/detail/interface_iarchive.hpp:74:15: note:   initializing argument 1 of ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = Porsche*; Archive = boost::archive::binary_iarchive]’
         Archive & operator&(T & t){
    
    

    Danke nochmal für die Hilfe!!



  • @mika000 sagte in Boost serialization - abstrakte Klasse "templates may not be virtual":

    ss & audi.get();

    Das ist doch nicht "ohne Zeiger". Ohne Zeiger wäre

    Audi audi{ ... };
    archive & audi;
    

    Ansonsten kannst du noch probieren

       {
            std::unique_ptr<Car> audi = std::make_unique<Audi>("Wilma", 3, "Rene", "Argentina" ,arma::randu<arma::mat>(4,5));
            audi->getInfo();
    
            std::unique_ptr<Car> porsche = std::make_unique<Porsche>("Joe", 14, arma::randu<arma::mat>(6,5));
            porsche->getInfo();
    
            std::ofstream outputStream("bin.dat", std::ios::binary);
            boost::archive::binary_oarchive ar(outputStream);
            ar & audi;
            ar & porsche;
        }
    
        {
            std::unique_ptr<Car> audi;
            std::unique_ptr<Car> porsche;
    
            std::ifstream inputStream("bin.dat", std::ios::binary);
            boost::archive::binary_iarchive ar(inputStream);
            ar & audi;
            ar & porsche;
    
            audi->getInfo();
            porsche->getInfo();   
        }
    

    Und übrigens fehlt deiner Car Klasse auch ein virtueller Destruktor. Ohne werden in deinem Beispiel die konkreten Objekte nicht korrekt zerstört, da du sie ja über Car-Zeiger löscht.



  • Hallo zusammen,

    ich stehe auf dem Schlauch. Mit Hilfe von hustbaer und Th69 kam ich definitiv weiter aber ich bekomme trotzdem noch den gleichen Fehler wie oben. Hier ist der Code:

    #include <armadillo>
    
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/assume_abstract.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/split_member.hpp>
    #include <boost/serialization/export.hpp>
    
    #include <fstream>
    #include <iostream>
    #include <memory>
    #include <sstream>
    #include <vector>
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract
    
    //Serialization for Armadillo Matrices------------------
    BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)
    namespace boost::serialization {
        template<class Archive>
        void save(Archive & ar, const arma::mat &t, unsigned int version) {
            ar << t.n_elem;
            auto data = t.colptr(0);
            for (size_t K = 0; K < t.n_elem; ++K)
                ar << data[K];
        }
    
        template<class Archive>
        void load(Archive & ar, arma::mat &t, unsigned int version) {
            size_t n_elem;
            ar >> n_elem;
            t.set_size(n_elem);
            t.zeros();
            auto data = t.colptr(0);
            for (size_t K = 0; K < n_elem; ++K)
                ar >> data[K];
        }
    } // -----------------------------------------
    
    class Car {
    public:
        Car() = default;
        virtual double getInfo() = 0;
        virtual ~Car() = default;
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int version) {};
    };
    
    class Porsche : public Car {
    public:
        double getInfo() override { return 1.1; }
        Porsche(std::string owner1, int hp1, arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            A = A1; 
            
            }
        std::string owner;
        int hp{};
        arma::mat A;
        Porsche() = default;
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & boost::serialization::base_object<Car>(*this); //https://theboostcpplibraries.com/boost.serialization-class-hierarchies
            ar & owner;
            ar & hp;
            ar & A;
        }    
    
        
    };
    
    class Audi : public Car {
    public:
        double getInfo() override { return 2; }
        Audi(std::string owner1, int hp1, std::string second_owner1, std::string country1,  arma::mat A1)
            {
            owner = owner1;
            hp = hp1;
            second_owner = second_owner1; 
            country = country1;
            A = A1; 
            }
        Audi() = default;
    
        std::string owner;
        int hp{};
        std::string second_owner;
        std::string country;
        arma::mat A;
    
    private:
        friend class boost::serialization::access;
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & boost::serialization::base_object<Car>(*this); //https://theboostcpplibraries.com/boost.serialization-class-hierarchies
            ar & owner;
            ar & hp;
            ar & second_owner;
            ar & country;
            ar & A;
        }
    
    };
    
    BOOST_CLASS_EXPORT(Audi)
    BOOST_CLASS_EXPORT(Porsche)
    
    
    int main() {
       {
            std::unique_ptr<Car> audi = std::make_unique<Audi>("Wilma", 3, "Rene", "Argentina" ,arma::randu<arma::mat>(4,5));
            audi->getInfo();
    
            std::unique_ptr<Car> porsche = std::make_unique<Porsche>("Joe", 14, arma::randu<arma::mat>(6,5));
    
            porsche->getInfo();
            std::ofstream outputStream("bin.dat", std::ios::binary);
            boost::archive::binary_oarchive ss(outputStream);
            ss & *audi.get();
            ss & *porsche.get();
        }
    
        {
            std::unique_ptr<Audi> audi = std::make_unique<Audi>();
            std::unique_ptr<Porsche>porsche = std::make_unique<Porsche>();
    
            std::ifstream inputStream("bin.dat", std::ios::binary);
            boost::archive::binary_iarchive ss(inputStream);
            ss & *audi.get();
            ss & *porsche.get();
    
            std::cout << "audi: hp=" << audi->hp << "\n";
            std::cout << "porsche: hp=" << porsche->hp<< " owner=" << porsche->owner << " A=" << porsche->A <<"\n";
    
        }
        
    }
    

    @hustbaer ich habe den Code von deinem letzten Beitrag ausprobiert und ich bekomme folgende Fehler:

    In file included from /usr/include/boost/serialization/split_member.hpp:23:0,
                     from /usr/include/boost/serialization/nvp.hpp:26,
                     from /usr/include/boost/serialization/array.hpp:19,
                     from /usr/include/boost/archive/basic_binary_iprimitive.hpp:53,
                     from /usr/include/boost/archive/binary_iarchive_impl.hpp:20,
                     from /usr/include/boost/archive/binary_iarchive.hpp:20,
                     from virt_funk_seri.cpp:3:
    /usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = std::unique_ptr<Car>]’:
    /usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/archive/detail/oserializer.hpp:149:40:   required from ‘void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::binary_oarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/archive/detail/oserializer.hpp:102:1:   required from ‘class boost::archive::detail::oserializer<boost::archive::binary_oarchive, std::unique_ptr<Car> >’
    /usr/include/boost/archive/detail/oserializer.hpp:254:13:   required from ‘static void boost::archive::detail::save_non_pointer_type<Archive>::save_standard::invoke(Archive&, const T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive]’
    /usr/include/boost/archive/detail/oserializer.hpp:309:22:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
    /usr/include/boost/archive/detail/common_oarchive.hpp:70:22:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&) [with T = const std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive]’
    /usr/include/boost/archive/basic_binary_oarchive.hpp:80:7:   required from ‘void boost::archive::basic_binary_oarchive<Archive>::save_override(const T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive]’
    /usr/include/boost/archive/binary_oarchive_impl.hpp:59:9:   required from ‘void boost::archive::binary_oarchive_impl<Archive, Elem, Tr>::save_override(T&) [with T = const std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive; Elem = char; Tr = std::char_traits<char>]’
    /usr/include/boost/archive/detail/interface_oarchive.hpp:70:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(const T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive]’
    /usr/include/boost/archive/detail/interface_oarchive.hpp:77:32:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator&(const T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_oarchive]’
    virt_funk_seri.cpp:173:14:   required from here
    /usr/include/boost/serialization/access.hpp:116:11: error: ‘class std::unique_ptr<Car>’ has no member named ‘serialize’
             t.serialize(ar, file_version);
             ~~^~~~~~~~~
    /usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::unique_ptr<Car>]’:
    /usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/archive/detail/iserializer.hpp:188:40:   required from ‘void boost::archive::detail::iserializer<Archive, T>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::binary_iarchive; T = std::unique_ptr<Car>]’
    /usr/include/boost/archive/detail/iserializer.hpp:120:1:   required from ‘class boost::archive::detail::iserializer<boost::archive::binary_iarchive, std::unique_ptr<Car> >’
    /usr/include/boost/archive/detail/iserializer.hpp:410:13:   required from ‘static void boost::archive::detail::load_non_pointer_type<Archive>::load_standard::invoke(Archive&, const T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/detail/iserializer.hpp:462:22:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
    /usr/include/boost/archive/detail/common_iarchive.hpp:66:22:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/basic_binary_iarchive.hpp:75:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/binary_iarchive_impl.hpp:58:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
    /usr/include/boost/archive/detail/interface_iarchive.hpp:68:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/detail/interface_iarchive.hpp:75:32:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = std::unique_ptr<Car>; Archive = boost::archive::binary_iarchive]’
    virt_funk_seri.cpp:183:14:   required from here
    /usr/include/boost/serialization/access.hpp:116:11: error: ‘class std::unique_ptr<Car>’ has no member named ‘serialize’
    
    

    Danke im Voraus.



  • Funktioniert denn die Variante ohne Zeiger (bzw. std::unique_ptr)?

    Und du mußt wohl <boost/serialization/unique_ptr.hpp> einbinden, s.a. die Antwort(en) in boost serialization std::unique_ptr support (bzw. auf eine neuere Boost-Version wechseln, falls der Header noch nicht vorhanden ist).

    Vllt. solltest du auch lernen, die Internet-Suche zu benutzen? Dafür, daß ich Boost-Serialisation noch niemals benutzt habe, ...



  • Was ist genau der Weg ohne Zeiger? Ich habe das nicht komplett verstanden.

            std::unique_ptr<Car> audi = std::make_unique<Audi>("Wilma", 3, "Rene", "Argentina" ,arma::randu<arma::mat>(4,5));
    

    sollte was genau sein?





  • Ja aber es müsste als Car definiert sein um die gleiche API zu verwenden. Ich habe früher so ausprobiert:

            std::unique_ptr<Audi> audi(new Audi);
    

    und es hat geklappt. Allerdings brauche ich das am Ende nicht.



  • Also am Ende bräuchte ich

           std::unique_ptr<Car> audi(new Audi);
           audi->getInfo();
           audi->A = arma::randu<arma::mat>(4,5);
           audi->hp = 3;
    

    und dafür braucht man dann virtuelle Funktionen in Car.



  • @mika000
    Probier mal

    #include <boost/serialization/unique_ptr.hpp>
    

    Ansonsten...
    Hier ein funktionierendes Beispielprogramm:

    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/serialization/assume_abstract.hpp>
    #include <boost/serialization/export.hpp>
    #include <boost/serialization/unique_ptr.hpp> // unique_ptr support
    #include <memory>
    #include <sstream>
    #include <iostream>
    
    class FooBase {
    public:
        virtual ~FooBase() = default;
        virtual char const* type() const = 0;
        virtual int get() const = 0;
        virtual void increment() = 0;
    
    private:
        friend class boost::serialization::access;
        template<class A>
        void serialize(A& ar, const unsigned int version) {
        }
    };
    
    class Foo : public FooBase {
    public:
        Foo() :i{ 100 } {}
    
        char const* type() const override { return "Foo"; }
        int get() const override { return i; }
        void increment() override { i++; }
    
    private:
        int i;
    
        friend class boost::serialization::access;
        template<class A>
        void serialize(A& ar, const unsigned int version) {
            // müssen wir aufrufen, obwohl die basisklasse leer ist.
            // die funktion wird benötigt damit Boost.Serialization die klassenhierarchie versteht und beim (de)serialisieren richtig casten kann
            ar& boost::serialization::base_object<FooBase>(*this);
            ar& i;
        }
    };
    
    class NullFoo : public FooBase {
    public:
        char const* type() const override { return "NullFoo"; }
        int get() const override { return 0; }
        void increment() override {}
    
    private:
        friend class boost::serialization::access;
        template<class A>
        void serialize(A& ar, const unsigned int version) {
            // müssen wir aufrufen, obwohl die basisklasse leer ist.
            // die funktion wird benötigt damit Boost.Serialization die klassenhierarchie versteht und beim (de)serialisieren richtig casten kann
            ar& boost::serialization::base_object<FooBase>(*this);
        }
    };
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(FooBase);
    BOOST_CLASS_EXPORT(Foo);
    BOOST_CLASS_EXPORT(NullFoo);
    
    int main() {
        std::string str;
        {
            std::unique_ptr<FooBase> of1 = std::make_unique<Foo>();
            of1->increment();
            of1->increment();
            of1->increment();
            std::unique_ptr<FooBase> of2 = std::make_unique<NullFoo>();
            std::cout << of1->type() << ": " << of1->get() << std::endl;
            std::cout << of2->type() << ": " << of2->get() << std::endl;
    
            std::stringstream strs;
            boost::archive::binary_oarchive ar(strs);
            ar& of1;
            ar& of2;
    
            str = strs.str();
        }
        {
            std::unique_ptr<FooBase> lf1;
            std::unique_ptr<FooBase> lf2;
    
            std::stringstream strs(str);
            boost::archive::binary_iarchive ar(strs);
            ar& lf1;
            ar& lf2;
    
            std::cout << lf1->type() << ": " << lf1->get() << std::endl;
            std::cout << lf2->type() << ": " << lf2->get() << std::endl;
        }
    }
    

    Ich hab deinen Code jetzt nicht genau durchgeschaut ob da ausser dem include noch etwas fehlt/falsch ist - das kannst du aber anhand dieses funktionierenden Beispiels auch selbst machen.



  • Dein Code kann aber gar nicht so funktionieren, denn bisher hast du nur getInfo() als virtuelle Funktion in der Basisklasse Car (und für die beiden anderen Member bräuchtest du eine Audi-Variable - bzw. einen passenden Cast)...

    Hast du denn jetzt mal #include <boost/serialization/unique_ptr.hpp> ausprobiert?



  • Vielen vielen Dank @hustbaer. Ich gehe gerade durch deinen Code.

    Ja @Th69 ich habe

    #include <boost/serialization/unique_ptr.hpp>
    

    ausprobiert. Hat leider nichts geändert. Kannst du darlegen, was du mit getInfo() meinst? Hier ist der Code, den ich vorher meinte anstatt:

           std::unique_ptr<Car> audi(new Audi);
    

    gibt es

           std::unique_ptr<Audi> audi(new Audi);
    

    und da hat alles mit getInfo() geklappt:

    #include <armadillo>
    
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/assume_abstract.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/split_member.hpp>
    
    #include <fstream>
    #include <iostream>
    #include <memory>
    #include <sstream>
    #include <vector>
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract
    
    //Serialization for Armadillo Matrices------------------
    BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)
    namespace boost::serialization {
        template<class Archive>
        void save(Archive & ar, const arma::mat &t, unsigned int version) {
            ar << t.n_elem;
            auto data = t.colptr(0);
            for (size_t K = 0; K < t.n_elem; ++K)
                ar << data[K];
        }
    
        template<class Archive>
        void load(Archive & ar, arma::mat &t, unsigned int version) {
            size_t n_elem;
            ar >> n_elem;
            t.set_size(n_elem);
            t.zeros();
            auto data = t.colptr(0);
            for (size_t K = 0; K < n_elem; ++K)
                ar >> data[K];
        }
    } // boost::serialization
    
    class Car {
    public:
          virtual double getInfo() = 0;
    
    private:
    //    template <typename Archive>
    //    virtual void serialize(Archive& ar, unsigned int version) = 0;
    };
    
    class Porsche : public Car {
    public:
        double getInfo() override { return 1.1; }
    
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & owner;
            ar & hp;
            ar & A;
        }
    
    public:
        std::string owner;
        int hp{};
        arma::mat A;
    };
    
    class Audi : public Car {
    public:
        double getInfo() override { return 2; }
    
        template <typename Archive>
        void serialize(Archive& ar, unsigned int) {
            ar & owner;
            ar & hp;
            ar & second_owner;
            ar & country;
            ar & A;
        }
    
    public:
        std::string owner;
        int hp{};
        std::string second_owner;
        std::string country;
     arma::mat A;
    };
    
    int main() {
        {
            std::unique_ptr<Audi> audi(new Audi);
            audi->getInfo();
            audi->A = arma::randu<arma::mat>(4,5);
            audi->hp = 3;
    
            std::unique_ptr<Porsche> porsche(new Porsche);
            porsche->getInfo();
            porsche->A = arma::randu<arma::mat>(6,5);
            porsche->hp = 14;
            porsche->owner = "Joe";
    
            std::ofstream outputStream("bin.dat", std::ios::binary);
    //      boost::archive::text_oarchive ss(outputStream);
            boost::archive::binary_oarchive ss(outputStream);
            ss & *audi.get();
            ss & *porsche.get();
        }
    
        {
            std::unique_ptr<Audi> audi(new Audi);
            std::unique_ptr<Porsche>porsche(new Porsche);
    
            std::ifstream inputStream("bin.dat", std::ios::binary);
    //      boost::archive::text_oarchive ss(outputStream);
            boost::archive::binary_iarchive ss(inputStream);
            ss & *audi.get();
            ss & *porsche.get();
    
            std::cout << "audi: hp=" << audi->hp << "\n";
            std::cout << "porsche: hp=" << porsche->hp << " owner=" << porsche->owner << " A=" << porsche-> A <<"\n";
    
        }
    }
    


  • Dieser Beitrag wurde gelöscht!


  • @mika000
    Ich glaube schön langsam das Problem ist dass du quasi keinen Plan hast davon was du da tust/versuchst zu tun.
    Lern C++.

    Konkret zu deiner Frage: Natürlich kannst du über einen Car-Zeiger nicht auf "hp" zugreifen, da Car kein Member "hp" hat. Wie soll das gehen?
    D.h. du wirst deine Car-Klasse erweitern müssen. Sieh dir mein Beispiel an, da sind die Grundzüge enthalten.


Anmelden zum Antworten