Boost - class has no member named ‘serialize’ (abstract class)? - c++

I'm trying to serialize my abstract class according to those questions:
Get private data members for non intrusive boost serialization C++
Error serializing an abstract class with boost
Error serializing an abstract class with boost
My neuron.h looks like this:
class Neuron {
public:
struct access;
API virtual ~Neuron();
API virtual double activate( double x, double b ) = 0;
};
I have to keep all the Boost related members in neuron.cpp to prevent including Boost headers when using neuron.h in some other codes.
My neuron.cpp looks like this:
#include "Neuron.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Neuron);
struct Neuron :: access {
template <class Archive>
static void serialize(Archive &ar, Neuron& n, const unsigned int version) {}
};
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, Neuron& n, const unsigned int version)
{
Neuron::access::serialize(ar, n, version);
}
} // namespace serialization
} // namespace boost
Neuron::~Neuron() {
}
The problem is, that when I'm using its inherited classes elsewhere, I'm getting the error
***/boost/boost/serialization/access.hpp:116:11: error: ‘class Neuron’ has no member named ‘serialize’
What am I doing wrong here?

I think the key here is "when I'm using its inherited classes elsewhere". Correct me (and your question, please) if I'm wrong, but this suggests that you are getting the compile error while compiling a source file other than neuron.cpp.
This makes sense, given what the compiler has to work with. You might have noticed that changes to one source file tend to not require re-compiling other source files. So adding something -- like an overload of serialize() -- to neuron.cpp does not change how other translation units are compiled. (It can change how everything is linked together in the end, but we're not there yet.) If another translation unit tries to serialize Neuron, the stuff in neuron.cpp does not matter. The compiler is not aware of an appropriate overload of serialize(), so serializing Neuron in another source file results in intrusive serialization. That is, the compiler will look for a member function of Neuron called serialize().
In order for your overload of serialize() to affect how other translation units are compiled, it needs to be declared in a header file.
Since you cannot put Boost stuff in neuron.h, you might have to create a new header file, say neuron_boost.h. This file would #include "neuron.h" then provide the declarations needed for Boost serialization. Source files that serialize descendants of Neuron would include neuron_boost.h while other source files could continue to include the original neuron.h.

Related

C++ Multiple Libraries Define Same Class Name

I am developing a project in which I have a vendor library, say vendor.h, for the specific Arduino-compatible board I'm using which defines class HTTPClient that conflicts with an Arduino system library, HTTPClient.h, which also defines class HTTPClient.
These two classes are unrelated other than having the same name, and the vendor implementation of an HTTP client is far less capable than the Arduino system library's implementation, so I'd prefer to use the latter. But I can't omit including the former, because I need quite a bit from the vendor.h. Essentially, I have the problem posed here, but with classes rather than functions. I have the full code of both, but given that one is a system library and the other is a vendor library, I'm reluctant to fork and edit either, as that adds lots of merging work down the road if either of them are updated, so my preference would be to find a tidy solution that doesn't edit either header.
I've tried a variety of solutions posted in other SO questions:
I do not want to leave out either header, as I need vendor.h for quite a few things and need the capabilities of HTTPClient.h's client implementation
Proper namespaces in the headers would solve the problem, I would prefer to avoid editing either header
I tried wrapping the #include <HTTPClient.h> in a namespace in my main.cpp, but that caused linking errors, as it's not a header-only library, so the header & cpp weren't in the same namespace
I tried a simple wrapper as proposed for the function in the above linked SO question in which the header contained just a forward declaration of my wrapper class & the associated cpp contained the actual class definition. This gave a compiler error of error: aggregate 'HTTP::Client client' has incomplete type and cannot be defined (Code sample of this attempt below)
main.cpp:
#include <vendor.h>
#include "httpclientwrapper.h"
HTTP::Client client;
httpclientwrapper.h:
#ifndef INC_HTTPCLIENTWRAPPER_H
#define INC_HTTPCLIENTWRAPPER_H
namespace HTTP {
class Client;
}
#endif
httpclientwrapper.cpp:
#include "httpclientwrapper.h"
#include <HTTPClient.h>
namespace HTTP {
class Client : public ::HTTPClient {};
}
In that example, I can't inherit from HTTPClient in a class definition in my header, as that will reintroduce the duplicate class name to the global namespace in my main program (hence the perhaps misguided attempt to see if a forward declaration would do the trick). I suspect that I can resolve the issue by completely duplicating the class definition of HTTPClient in my wrapper class above rather than trying to use inheritance. I would then add member definitions to my wrapper cpp which pass the call to HTTPClient's members. Before I go through the trouble of rewriting (or more likely, copy/pasting) the entire HTTPClient definition from HTTPClient.h into my own wrapper, I was wondering if there was a better or more proper way to resolve the conflict?
Thanks for you help!
As a solution was never proposed, I'm posting an answer that summarizes my research and my ultimate resolution. Mostly, I encourage the use of namespaces, because proper uses of namespaces would have eliminated the conflict. However, Arduino environments try to keep things simple to lower the barrier of entry, eschewing "complicated" features of C++, so more advanced use cases will likely continue to run into issues like this. From other SO answers and forum posts (cited where I could), here are some methods for avoiding name conflicts like this:
If you can edit the source
Edit the source code to remove the conflict or add a namespace to one of both libraries. If this is an open source library, submit a pull request. This is the cleanest solution. However, if you can't push your changes back upstream (such as when one is a system library for some hardware), you may end up with merge issues down the road when the maintainer/developer updates the libraries.
If you can't edit the source
Credit for part of this: How to avoid variable/function conflicts from two libraries in C++
For libraries that are header only libraries (or all functions are inline)
(ie, they have only a .h file without a .o or .cpp)
Include the library inside a namespace. In most code, this is frowned upon as poor form, but if you're already in a situation where you are trying to cope with a library that doesn't contain itself nicely, it's a clean and simple way to contain the code in a namespace and avoid name conflicts.
main.cpp
namespace foo {
#include library.h
}
int main() {
foo::bar(1);
}
For libraries with functions
The above method will fail to link at compile time, because the declarations in the header will be inside the namespace, but the definitions of those functions are not.
Instead, create a wrapper header and implementation file. In the header, declare your namespace and functions you wish to use, but do not import the original library. In the implementation file, import your library, and use the functions inside your new namespaced functions. That way, the one conflicting library is not imported into the same place as the other.
wrapper.h
namespace foo {
int bar(int a);
}
wrapper.cpp
#include "wrapper.h"
#include "library.h"
namespace foo {
int bar(int a) {
return ::bar(a);
}
}
main.cpp
#include "wrapper.h"
int main() {
foo::bar(1);
}
You could also, for the sake of consistency, wrap both libraries so they're each in their own namespace. This method does mean that you will have to put in the effort to write a wrapper for every function you plan to use. This gets more complicated, however, when you need to use classes from the library (see below).
For libraries with classes
This is an extension of the wrapper function model from above, but you will need to put in more work, and there are a few more drawbacks. You can't write a class that inherits from the library's class, as that would require importing the original library in your wrapper header prior to defining your class, so you must write a complete wrapper class. You also cannot have a private member of your class of the type from the original class that you can delegate calls to for the same reason. The attempt at using a forward declaration I described in my question also did not work, as the header file needs a complete declaration of the class to compile. This left me the below implementation, which only works in the cases of a singleton (which was my use case anyway).
The wrapper header file should almost completely duplicate the public interface of the class you want to use.
wrapper.h
namespace foo {
Class Bar() {
public:
void f(int a);
bool g(char* b, int c, bool d);
char* h();
};
}
The wrapper implementation file then creates an instance and passes the calls along.
wrapper.cpp
#include "wrapper.h"
#include "library.h"
namespace foo {
::Bar obj;
void Bar::f(int a) {
return obj.f(a);
}
bool Bar::g(char* b, int c, bool d) {
return obj.g(b, c, d);
}
char* Bar::h() {
return obj.h();
}
}
The main file will interact with only a single instance of the original class, no matter how many times your wrapper class in instantiated.
main.cpp
#include "wrapper.h"
int main() {
foo::Bar obj;
obj.f(1);
obj.g("hello",5,true);
obj.h();
}
Overall, this strikes me as a flawed solution. To fully wrap this class, I think the this could be modified to add a factory class that would be fully contained inside the wrapper implementation file. This class would instantiate the original library class every time your wrapper class is instantiated, and then track these instances. In this way, your wrapper class could keep an index to its associated instance in the factory and bypass the need to have that instance as its own private member. This seemed like a significant amount of work, and I did not attempt to do so, but would look something like the code below. (This probably needs some polish and a real look at its memory usage!)
The wrapper header file adds a constructor & private member to store an instance id
wrapper.h
namespace foo {
Class Bar() {
public:
Bar();
void f(int a);
bool g(char* b, int c, bool d);
char* h();
private:
unsigned int instance;
};
}
The wrapper implementation file then adds a factory class to manage instances of the original library's class
wrapper.cpp
#include "wrapper.h"
#include "library.h"
namespace foo {
class BarFactory {
public:
static unsigned int new() {
instances[count] = new ::Bar();
return count++;
}
static ::Bar* get(unsigned int i) {
return instances[i];
}
private:
BarFactory();
::Bar* instances[MAX_COUNT]
int count;
};
void Bar::Bar() {
instance = BarFactory.new();
}
void Bar::f(int a) {
return BarFactory.get(i)->f(a);
}
bool Bar::g(char* b, int c, bool d) {
return BarFactory.get(i)->g(b, c, d);
}
char* Bar::h() {
return BarFactory.get(i)->h();
}
}
The main file remains unchanged
main.cpp
#include "wrapper.h"
int main() {
foo::bar obj;
obj.f(1);
obj.g("hello",5,true);
obj.h();
}
If all of this seems like a lot of work, then you're thinking the same thing I did. I implemented the basic class wrapper, and realized it wasn't going to work for my use case. And given the hardware limitations of the Arduino, I ultimately decided that rather than add more code to be able to use the HTTPClient implementation in either library, I wrote my own HTTP implementation library in the end, and so used none of the above and saved several hundred kilobytes of memory. But I wanted to share here in case somebody else was looking to answer the same question!

How to create a derived class of base class with no virtual methods?

So I have the following situation: I have a (C++) driver that is not in my control that I have the headers and library files for but no source code. I want to simulate the driver in my SW (not just for tests, but use the same code as for the actual implementation). It would be easy to just create a derived class from the base class and re-implement all the methods except none of the methods in the driver base are marked as virtual so I cannot inherit them and still use the same base type in my code. I cannot create a custom header just for the simulation version because I want to be able to use the same code for simulation or real driver. I'm a bit stumped, how do I create a derived class from this non-virtual base?
If Driver does not offer virtual functions, then having code which uses Driver * use implementations from a class derived from Driver is not possible.
However, you could change your code to be templated by the type of driver use and use two instantiations, one for Driver and one for SimulationDriver (which even wouldn't have to be derived from Driver). Note that in this particular case (where you know all desired instantiations), you can sidestep the usual requirement of "all template code must be in header files" by using explicit instatiation. I use something similar in one of my projects.
Basically, code which currently looks like this:
file.hpp
class Driver;
void process(const Driver *d);
file.cpp
#include "file.hpp"
#include "Driver.h"
void process(const Driver *d)
{
d->doStuff();
}
will change to look like this:
file.hpp
template <class T_Driver>
void process(const T_Driver *d);
file.cpp
#include "file.hpp"
#include "Driver.h"
#include "SimulationDriver.h"
template <class T_Driver>
void process(const T_Driver *d)
{
d->doStuff();
}
template void process(const Driver *d);
template void process(const SimulationDriver *d);

Why do I have to include the implementation file in class derived from a template class?

Simple question - why do I have to #include "listType.cpp" or get linker errors here? Why can't I just include the header?
stockListType.h:
#ifndef stockListType_H
#define stockListType_H
#include "listType.h"
#include "stockType.h"
#include "listType.cpp"
using namespace std;
class stockListType : public listType<stockType>
{
private:
unique_ptr<int[]> sortIndicesByGainLoss;
public:
void sortByStockSymbol();
void sortByGainLoss();
stockListType(int maxSize);
};
#endif
This happens because in a traditional C++ compiler approach template code "doesn't exist" as a "material execution entity" until it's instantiated for some "real" types (stockType in your case). There're however techniques called explicit instantiation which allows to to specify during processing of "listType.cpp" that later you will need an instance of the code for e.g. stockType, otherType and int. Read from this: http://msdn.microsoft.com/en-us/library/by56e477.aspx or this: http://www.cplusplus.com/forum/articles/14272/ or this: How do I explicitly instantiate a template function?
Also another reason for using a source, not pre-compiled code of template classes and functions is that it's possible to override later an implementation of a given template class, method or function for a particular template argument (recall the famous std::cout << "Hello, World " << 1 << MyClassObject << std::endl, that's the classical case when operator<<(ostream&, T&) is defined for each particular type separately.
Besides, if you take a look into standard C++ STL library (e.g. <vector> or <string>) you will see that the whole code of the classes is right in header files, or files included from header files (.tcc) even a rather complex one (see Boost.Spirit, well, if you're brave enough :) ). That's because it's not possible to create an executable code for vector until vector elements (stockType etc) are defined.

function template specialization ignored by the compiler

Our project uses boost::serialization to serialize many things.
But some types are not correctly registered and when serializing them we get an "unregistered class" error
I have narrowed the problem to the BOOST_CLASS_EXPORT_KEY, which, for some types are not generating code.
What BOOST_CLASS_EXPORT_KEY does is :
namespace boost {
namespace serialization {
template<>
struct guid_defined< T > : boost::mpl::true_ {};
template<>
inline const char * guid< T >(){
return K;
}
} /* serialization */
} /* boost */
All objects that are serialized inherit from a base class called Serializable.
Serialization is always done via a pointer to the base class.
This works fine except for one case:
There is a class template SerializableList which is a Serializable which holds a list of T
template< typename T>
class SerializableList
{
...
std::vector<T> m_list;
template<class Archive>
void serialize( Archive & ar, const unsigned int /*version*/ )
{
ar & boost::serialization::base_object<businessObjects::Serializable>(*this);
ar & mList;
}
};
in a dedicated cpp and hpp files we then declare each instantiation of this template to boost serialization like this:
hpp:
BOOST_CLASS_EXPORT_KEY( SerializableList<SomeT*> );
BOOST_CLASS_EXPORT_KEY( SerializableList<SomeOtherT*> );
BOOST_CLASS_EXPORT_KEY( SerializableList<AThirdT*> );
cpp:
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<SomeT*> );
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<SomeOtherT*> );
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<AThirdT*> );
But half of these lines do not produce executable code in the final executable! if we put a breakpoint on each of those lines and run, half the breakpoints disappear, those who stay are on the working types (those we can serialize).
For instance the breakpoints would stay on SerializableList<SomeT*> and SerializableList<AThirdT*> but not SerializableList<SomeOtherT*>.
Btw, we have also tried to call directly boost::serialization::guid<T>(), and while it works fine for say:
boost::serialization::guid<SerializableList<SomeT*> >() which returns the key,
it doesn't for
boost::serialization::guid<SerializableList<SomeOtherT*> >() which calls the default implementation ...
So is there a compiler bug (we use Visual C++ 2010 SP1), or some good reason for the compiler to ignore some of those specializations?
I forgot to mention, all this code lies in a library, which is linked against the exe project. I've tried with different exe projects and sometimes it works sometimes it doesn't ... the compilation options are the same... I really have no clue what's going on :'(
We found the solution,
One (serializable) class had several SerializableList members, and did not include the file with all the "BOOST_CLASS_EXPORT_KEY" lines.
the other projects which were working didn't use that particular class ...

Boost serialization unregistered class errors

I cannot seem to get boost::serialization to work well. I have sprinkled the class .cpp files with BOOST_CLASS_EXPORT_GUID macros, after including the class and archive headers, but I still get unregistered_class exceptions.
I have looked around and it seems that whatever I can find is 1. either outdated, dealing with old versions of the library, or 2. works only for a simple one-file solution in which all the serializable classes are defined one after the other. Nothing I've found helps.
My solution at present consists of a project, compiled into a static library, that contains the core functionality with the basic archivable classes, and another test project that will eventually be fleshed out into a more concrete logic layer. Getting everything to work with boost::serialization is proving a nightmare. I'm almost tempted to write it myself.
Anyway, the class in question which raises the exception is defined in a header, which looks something like this:
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/serialization.hpp>
// Other includes...
namespace GameCore { class Component; }
// Forward declare some boost::serialization functions that appear at the bottom.
// ...
BOOST_SERIALIZATION_ASSUME_ABSTRACT(GameCore::Component);
namespace GameCore
{
// Some forward declares..
//////////////////////////////////////////////////////////////////////////
// Base component type.
//////////////////////////////////////////////////////////////////////////
class Component : public Updatable, public Object
{
friend class boost::serialization::access;
protected:
template <typename Archive>
friend void boost::serialization::serialize(Archive& archive, Component& object, const unsigned int version);
template <typename Archive> friend void boost::serialization::load_construct_data(Archive& archive, Component* t, const unsigned int version);
template <typename Archive> friend void boost::serialization::save_construct_data(Archive& archive, const Component* t, const unsigned int version);
public:
Component(GameObject& owner);
virtual ~Component() = 0;
// Irrelevant stuff..
GameObject& gameObject;
Transform* transform;
};
}
// The component includes have to be placed here because it would otherwise create a cyclic inclusion when trying to compile the
// individual component classes, say, Transform, which would end up including itself.
#include "Transform.h"
namespace boost
{
namespace serialization
{
template<class Archive>
inline void save_construct_data(Archive& archive, const GameCore::Component* t, const unsigned int version)
{
archive << t->gameObject;
}
template<class Archive>
inline void load_construct_data(Archive& archive, GameCore::Component* t, const unsigned int version)
{
// Retrieve data from archive required to construct new instance.
GameCore::GameObject owner;
archive >> owner;
// Invoke inplace constructor to initialize instance of class.
::new(t)GameCore::Component(owner);
}
//////////////////////////////////////////////////////////////////////////
// Serialization function for save/load.
//////////////////////////////////////////////////////////////////////////
template <typename Archive>
void serialize(Archive& archive, GameCore::Component& t, const unsigned int version)
{
archive & boost::serialization::base_object<GameCore::Object>(t);
archive & boost::serialization::base_object<GameCore::Updatable>(t);
archive & t.gameObject;
archive & t.transform;
}
}
}
That is one header file. Sorry for the verbosity. Its .cpp file starts like this:
#include "Component.h"
#include <boost/serialization/export.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
// Other includes...
BOOST_CLASS_EXPORT_GUID(GameCore::Component, "GameCore::Component");
// Class method definitions here.
The exception is raised when I try to archive an instance object that derives from Component, which itself is an abstract class. I'm archiving through a simple method defined in a different manager class:
std::ofstream outputFile(fileName);
boost::archive::text_oarchive outputArchive(outputFile);
outputArchive << objects;
where objects is a std::list of Objects. Object is the base class from which all things, including Components, derive.
I apologize if this sounds convoluted, but there's only three layers of inheritance, and I believe I had a neat and effective architecture before thoughts of serialization crept in.
If you could help me get rid of the irrational unregistered_class exceptions I'll light a candle for your souls!
Update: Funny thing is, the exception isn't raised for all derived classes of Component.
After frying my neurones looking for an answer, I stumbled upon this line in the documentation:
Static Libraries and Serialization
Code for serialization of data types can be saved in libraries just as
it can for the rest of the type implementation. This works well, and
can save huge amount of compilation time. Only compile serialization
definitions in the library. Explicitly instantiate serialization code
for ALL archive classes you intend to use in the library. For exported
types, only use BOOST_CLASS_EXPORT_KEY in headers. For exported types,
only use BOOST_CLASS_EXPORT_IMPLEMENT in definitions compiled in the
library. For any particular type, there should be only one file which
contains BOOST_CLASS_EXPORT_IMPLEMENT for that type. This ensures that
only one copy of serialization code will exist within the program. It
avoids wasted space and the possibility of having different versions
of the serialization code in the same program. Including
BOOST_CLASS_EXPORT_IMPLEMENT in multiple files could result in a
failure to link due to duplicated symbols or the throwing of a runtime
exception.
Splitting BOOST_CLASS_EXPORT into BOOST_CLASS_EXPORT_KEY and BOOST_CLASS_EXPORT_IMPLEMENT seems to work.