diff --git a/stream.cpp b/stream.cpp
index ce882221f6836fabc7c2d0c9c37557b66999303f..039caf0c534248defcf45c32eeae562c3a8cd548 100644
--- a/stream.cpp
+++ b/stream.cpp
@@ -43,10 +43,7 @@ void TypePoolStream::unserializeUnknownImpl(const string& name, istream& is, str
         throw TscppException("unknown type",name);
     }
 
-    unique_ptr<char[]> unserialized(new char[it->second.size]);
-    is.read(reinterpret_cast<char*>(unserialized.get()),it->second.size);
-    if(is.eof()) throw TscppException("eof");
-    it->second.usc(unserialized.get());
+    it->second(is);
 }
 
 void OutputArchive::serializeImpl(const char *name, const void *data, int size)
diff --git a/stream.h b/stream.h
index 6a026c3e7b046df919c3adfe4eab0f2594214353..a46d100f6c932781a148b0864d3364a97233a0a1 100644
--- a/stream.h
+++ b/stream.h
@@ -49,6 +49,48 @@
 
 namespace tscpp {
 
+/**
+ * Exception class thrown by the input archives
+ */
+class TscppException : public std::runtime_error
+{
+public:
+    /**
+     * \internal
+     */
+    TscppException(const std::string& what) : runtime_error(what) {}
+    
+    /**
+     * \internal
+     */
+    TscppException(const std::string& what, const std::string& n)
+        : runtime_error(what), n(n) {}
+    
+    /**
+     * If the exception is thrown because an unknown/unexpected type has been
+     * found in the input stream, this member function allows to access the
+     * mangled type name.
+     * It is useful to print an error message with the name of the type in the
+     * stream
+     * \code
+     * InputArchive ia(is);
+     * Foo f;
+     * try {
+     *     ia>>f;
+     * } catch(TscppException& ex) {
+     *     if(ex.name().empty()==false)
+     *         cerr<<"While unserializing Foo, "<<demangle(ex.name())<<" was found\n";
+     *     else cerr<<ex.what()<<endl;
+     * }
+     * \endcode
+     * \return the serialized type name, or "" if eof was found
+     */
+    std::string name() const { return n; }
+
+private:
+    std::string n;
+};
+
 /**
  * Type pool for the TSCPP stream API.
  * A type pool is a class where you can register types and associate callbacks
@@ -69,7 +111,7 @@ public:
         #ifndef _MIOSIX
         static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
         #endif
-        types[typeid(T).name()]=UnserializerImpl(sizeof(T),[=](const void *buffer) {
+        types[typeid(T).name()]=[=](std::istream& is) {
             //NOTE: We copy the buffer to respect alignment requirements.
             //The buffer may not be suitably aligned for the unserialized type
             //TODO: support classes without default constructor
@@ -77,9 +119,10 @@ public:
             //destructor. However, since it is trivially copyable, we at least aren't
             //overwriting pointers to allocated memory.
             T t;
-            memcpy(&t,buffer,sizeof(T));
+            is.read(reinterpret_cast<char*>(&t),sizeof(T));
+            if(is.eof()) throw TscppException("eof");
             callback(t);
-        });
+        };
     }
     
     /**
@@ -88,19 +131,7 @@ public:
     void unserializeUnknownImpl(const std::string& name, std::istream& is, std::streampos pos) const;
     
 private:
-    /**
-     * \internal
-     */
-    class UnserializerImpl
-    {
-    public:
-        UnserializerImpl() : size(0) {}
-        UnserializerImpl(int size, std::function<void (const void*)> usc) : size(size), usc(usc) {}
-        int size;
-        std::function<void (const void*)> usc;
-    };
-
-    std::map<std::string,UnserializerImpl> types; ///< Registered types
+    std::map<std::string,std::function<void (std::istream&)>> types; ///< Registered types
 };
 
 /**
@@ -224,48 +255,6 @@ private:
     const TypePoolStream& tp;
 };
 
-/**
- * Exception class thrown by the input archives
- */
-class TscppException : public std::runtime_error
-{
-public:
-    /**
-     * \internal
-     */
-    TscppException(const std::string& what) : runtime_error(what) {}
-    
-    /**
-     * \internal
-     */
-    TscppException(const std::string& what, const std::string& n)
-        : runtime_error(what), n(n) {}
-    
-    /**
-     * If the exception is thrown because an unknown/unexpected type has been
-     * found in the input stream, this member function allows to access the
-     * mangled type name.
-     * It is useful to print an error message with the name of the type in the
-     * stream
-     * \code
-     * InputArchive ia(is);
-     * Foo f;
-     * try {
-     *     ia>>f;
-     * } catch(TscppException& ex) {
-     *     if(ex.name().empty()==false)
-     *         cerr<<"While unserializing Foo, "<<demangle(ex.name())<<" was found\n";
-     *     else cerr<<ex.what()<<endl;
-     * }
-     * \endcode
-     * \return the serialized type name, or "" if eof was found
-     */
-    std::string name() const { return n; }
-
-private:
-    std::string n;
-};
-
 /**
  * Demangle a C++ name. Useful for printing type names in error logs.
  * This function may not be supported in all platforms, in this case it returns