Bielan |
» 2017-04-02 20:28:40 Niestety nie otrzymasz takiego mechanizmu za darmo. Zapis typów wbudowanych jest prosty: można go wykonać za pomocą zapisu binarnego lub pośrednio przez string. Niestety typy definiowane przez użytkownika będą wymagały obsługi. Jeżeli chcesz zapisać na przykład jakiś typ użytkownika, który jest listą i ma tablicę wskaźników to po zapisaniu go i wczytaniu pozycje wskaźników będą nieprawidłowe ponieważ wczytane elementy będą gdzie indziej w pamięci. Wszystkie dane, które można traktować jak POD możesz zapisać binarnie wszystko inne musisz obsłużyć. Możesz próbować użyć czegoś gotowego np. |
|
marcolo2307 Temat założony przez niniejszego użytkownika |
» 2017-04-02 20:48:34 POD mi wystarczy, nie zamierzam tam trzymać naprawdę skomplikowanych klas, bardziej pojemniki na dane typu rozmiar okna, skala, kolor itd.
Ale w jaki sposób mam to wszystko przechować w jednym kontenerze? boost::any nie zapiszę do pliku, a void* nie usunę. |
|
Bielan |
» 2017-04-02 20:56:16 Chcę zapisu także wbudowanych typów: int, bool itd. Do tego np. std::string
|
POD mi wystarczy, nie zamierzam tam trzymać naprawdę skomplikowanych klas
|
1. std::string nie jest POD. 2. Poczytaj o: http://en.cppreference.com/w/cpp/memory/shared_ptr/get_deleter. Taki mechanizm wykorzystują inteligentne pointery. 3. Pamiętaj, że nie możesz wywołać delete na niczym co jest alokowane na stosie, czyli jak będziesz wrzucał na przemian struktury i wskaźniki do struktur to możesz mieć problem. |
|
mokrowski |
» 2017-04-02 21:09:02 Próbujesz rozwiązywać problem XY. W dodatku zmieniasz wymagania co do tego czego potrzebujesz w trakcie. I to niestety w sposób istotny. Usiądź zastanów się i powiedz czego dokładnie potrzebujesz. Najpierw (chociaż pobieżnie) zapoznaj się z tym:
http://xyproblem.info/ http://www.boost.org/doc/libs/1_63_0/doc/html/variant.html http://www.boost.org/doc/libs/1_63_0/doc/html/any.html http://www.boost.org/doc/libs/1_63_0/libs/serialization/doc/index.html https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Erasure https://developers.google.com/protocol-buffers/?hl=en
Oczywiście to potencjalny wycinek tego czego możesz potrzebować. Wystarczy jednak byś mógł to nazwać precyzyjnie. |
|
Elaine |
» 2017-04-02 21:38:49 boost::any nie zapiszę do pliku |
Więc użyj tej samej techniki, której używa boost::any, tylko rozszerz ją o zapis do pliku i co tam jeszcze potrzebujesz: #include <iostream> #include <map> #include <memory> #include <ostream> #include <string> #include <type_traits> #include <utility>
template < typename T, typename = std::enable_if_t < std::is_standard_layout < T > { } >> void save( std::ostream & stream, const T & thing ) { stream.write( reinterpret_cast < const char *>( std::addressof( thing ) ), sizeof( thing ) ); }
void save( std::ostream & stream, const std::string & string ) { const auto length = string.size(); save( stream, length ); stream.write( string.data(), static_cast < std::streamsize >( length ) ); }
struct erased_holder_base { public: virtual ~erased_holder_base() = default; erased_holder_base( const erased_holder_base & ) = delete; erased_holder_base & operator =( const erased_holder_base & ) = delete; virtual void save( std::ostream & stream ) = 0; protected: erased_holder_base() = default; };
template < typename T > class erased_holder final : public erased_holder_base { public: explicit erased_holder( T value ); void save( std::ostream & stream ) override; private: T value; };
template < typename T > erased_holder < T >::erased_holder( T value ) : value( std::move( value ) ) { }
template < typename T > void erased_holder < T >::save( std::ostream & stream ) { ::save( stream, value ); }
int main() { std::map < std::string, std::unique_ptr < erased_holder_base >> values; values.emplace( "foo", std::make_unique < erased_holder < int >>( 1 ) ); values.emplace( "bar", std::make_unique < erased_holder < double >>( 2.0 ) ); values.emplace( "qux", std::make_unique < erased_holder < std::string >>( "żółć" ) ); for( auto && value: values ) { value.second->save( std::cout ); } }
>> ./Release/blahblah | hd 00000000 00 00 00 00 00 00 00 40 01 00 00 00 08 00 00 00 |.......@........| 00000010 00 00 00 00 c5 bc c3 b3 c5 82 c4 87 |............| 0000001c
|
|
Elaine |
» 2017-04-02 21:56:04 W Booście jest też biblioteka do type erasure, która tutaj się świetnie nadaje: #include <iostream> #include <map> #include <memory> #include <ostream> #include <string> #include <type_traits> #include <boost/type_erasure/any.hpp> namespace te = boost::type_erasure;
template < typename T, typename = std::enable_if_t < std::is_standard_layout < T > { } >> void save( std::ostream & stream, const T & thing ) { stream.write( reinterpret_cast < const char *>( std::addressof( thing ) ), sizeof( thing ) ); }
void save( std::ostream & stream, const std::string & string ) { const auto length = string.size(); save( stream, length ); stream.write( string.data(), static_cast < std::streamsize >( length ) ); }
template < typename T = te::_self > struct saveable { static void apply( std::ostream & stream, const T & thing ) { save( stream, thing ); } };
namespace boost { namespace type_erasure { template < typename T, typename Base > struct concept_interface < saveable < T >, Base, T > : Base { void save( std::ostream & stream ) const { return call( saveable < T > { }, stream, * this ); } }; } }
using holder_type = te::any < boost::mpl::vector < te::destructible <>, saveable <>>>;
int main() { std::map < std::string, holder_type > values; values.emplace( "foo", 1 ); values.emplace( "bar", 2.0 ); values.emplace( "qux", std::string( "żółć" ) ); for( auto && value: values ) { value.second.save( std::cout ); } }
|
|
marcolo2307 Temat założony przez niniejszego użytkownika |
» 2017-04-02 22:08:09 Dzięki wszystkim za pomoc.
Alueril, nie jestem w stanie zrozumieć Twojego kodu, muszę poczytać o tych wszystkich klasach.
Postaram się jak najszybciej wykorzystać wasze materiały, ale jako iż jutro jest poniedziałek to najpierw muszę zająć się szkołą (btw. tylko u mnie przedmioty zawodowe polegają na przepisywaniu slajdów/monologu nauczyciela do zeszytu lub "praktycznym" liczeniu w systemach siódemkowych i czternastkowych?).
Edit:
Alueril, nie skorzystam z Twojego rozwiązania, jest dla mnie zbyt skomplikowane, mój kompilator nawet go nie akceptuje. Tak samo wolę się nie bawić w to co mi podesłałeś Bielan. Spróbuję to zrozumieć, ale obecnie chcę czegoś, co będzie działało i z czego będę mógł skorzystać wiedząc jak to działa.
Pozostaje mi chyba po prostu dziedziczyć po wspólnej klasie i starać się ograniczać liczbę typów, z których będę korzystać, tak będzie najprościej. Jeszcze raz dzięki za pomoc, temat pozostawiam otwarty, może ktoś jeszcze coś wymyśli.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
W sumie nie wiem czemu nie skorzystałem z tego wcześniej... W każdym razie zdecydowałem się na trzymanie danych POD w char*. Niestety stringi odpadają, trzeba korzystać ze zwykłych char*, ale w przyszłości po prostu dodam dla nich specjalną funkcję w stylu "addString".
Zamykam temat. |
|
1 « 2 » |