Working on a large project concerning C++ and Matlab cooperation through Mex we are currently struggling with one of our singletons.
The class is being generated through macros during preprocessing so it may seem a bit odd.
class AdditionalOperation {
private:
const std::string* val;
typedef std::map<std::string, const std::string*> StringMap;
static StringMap& getStringToPointerMap()
{
static StringMap map;
return map;
}
static boost::mutex& getMutex()
{
static boost::mutex mutex;
return mutex;
}
AdditionalOperation(const std::string* s)
:val(s)
{}
private:
static std::string* none_string()
{
static std::string s = "none";
static int count = 0;
boost::mutex::scoped_lock lock(getMutex());
if(count++ == 0) {
getStringToPointerMap().insert(std::make_pair(s,&s));
}
return &s;
}
public:
static AdditionalOperation none()
{
return AdditionalOperation(none_string());
}
private:
static std::string* norm_string()
{
static std::string s = "norm";
static int count = 0;
boost::mutex::scoped_lock lock(getMutex());
if(count++ == 0) {
getStringToPointerMap().insert(std::make_pair(s,&s));
}
return &s;
}
public:
static AdditionalOperation norm()
{
return AdditionalOperation(norm_string());
}
private:
static void prepare()
{
none();
norm();
}
public:
static AdditionalOperation fromString(std::string s)
{
static int count = 0;
if(count++ == 0)
prepare();
boost::mutex::scoped_lock lock(getMutex());
StringMap& map = getStringToPointerMap();
StringMap::iterator location = map.find(s);
if(location == map.end()) {
throw UnknownEnumValue(s);
}
return AdditionalOperation(location->second);
}
std::string toString() const
{
return *val;
}
bool operator==(const AdditionalOperation& other) const
{
return val == other.val;
}
bool operator!=(const AdditionalOperation& other) const
{
return !(*this == other);
}
};
All this code is generated from this line (through macros as stated above):
DECLARE_SENUM(AdditionalOperation, none, norm);
Which is a nice interface that we'd like to keep on using.
We want to use this class as a replacement for enumerations because we need to translate them from string and to a string. In this class we have 2 'enumeration' members namely norm and none.
Now we have added some logging and have determined that the insert operation inside the none_string and norm_string function is being called twice even though our counter should prevent this.
Some things we have tried :
We are working with a dynamic library but using -rdynamic did not help.
When we print the address of the static variables we can clearly see that they differ.
This class is situated within a dynamic library which in turn is linked with a mex file. This mex file is being dynamically loaded by another mex file through dlopen.
We were thinking that perhaps multiple instances of this class are declared and active because of the dynamic library. But we also use other kind of singletons that have not shown any sign of problems.
I hope it was clear enough, additional information or clarification can always be provided!
Thanks in advance!
You are, clearly, overcomplicating the problem.
std::string const& to_string(MyEnum e) {
static std::string const First = "First";
static std::string const Second = "Second";
switch(e) {
case MyEnum::First: return First;
case MyEnum::Second: return Second;
}
throw std::runtime_error("Unknown enum value");
}
would work as well, if not better and faster.
Related
What is the method to save and retrieve contents (to/from a disk file) of an object who has const member variables?
Or more specifically, const members demand an initialization at the creation time of the object. So, the retrieval of the content has to happen before the initializers (before { } of the constructor). If we are not minding the encapsulation, we can retrieve and create the object with parameters. How to do everything by keeping the data-hiding?
Compiler: C++ 14 and maybe beyond.
Instantiation of the object, filling the content and storing for next context.
{ //CODE BLOCK 1 : making of content and saving to a diskfile
Abcd abcd(65535,256,25);
//some operations on abcd
//save to disk
QFile abcdFile("abcd.lion");
abcdFile.open(QFile::WriteOnly);
abcd.serialize(abcdFile);
abcdFile.close();
}
using same object after taking from file.
{ //CODE BLOCK 2 : loading from file and continue in another context
QFile abcdFile("abcd.lion");
abcdFile.open(QFile::ReadOnly);
Abcd abcdNew(abcdFile);
abcdFile.close();
if(!abcdNew.isHealthy())
printf("abcd from hdd is NOT Healthy :(\n");
else
{
//doTheJob(abcdNew);
}
}
The class.
#include <QFile>
class Abcd
{
const bool _healthy;//true if properly initialized
//IMPORTANT: _healthy has to be the first member in the class.
//this is to execute its initializer list first
protected:
const long _rX;
const long _rY;
long _count;
public:
Abcd(const long refX,
const long refY,
const long count) :
_healthy(true),
_rX(refX), _rY(refY),
_count(count)
{
}
Abcd(QFile &src) :
_healthy(deserialize(src)),
//Hack. Actually the initialization happened by this statement.
//just keeping the below statements for the sake of syntactical correctness. :(
_rX(_rX), _rY(_rY)
//,_count(count)
{
}
virtual
~Abcd()
{
}
inline
bool isHealthy()
{
return _healthy;
}
bool serialize(QFile &dest)
{
if(dest.write((char *)&_rY,sizeof(_rY))!=sizeof(_rY)) return false;
if(dest.write((char *)&_rX,sizeof(_rX))!=sizeof(_rX)) return false;
if(dest.write((char *)&_count,sizeof(_count))!=sizeof(_count)) return false;
return true;
}
private:
bool deserialize(QFile &src)
{
if(src.read((char *)&_rY,sizeof(_rY))!=sizeof(_rY)) return false;
if(src.read((char *)&_rX,sizeof(_rX))!=sizeof(_rX)) return false;
if(src.read((char *)&_count,sizeof(_count))!=sizeof(_count)) return false;
return true;
}
};
Please suggest a better method. For this, I have introduced a ‘healthy’ status member as the first member in the declaration of the class. Also in deserialization, I am fooling the compiler by casting the const variable to char * pointer.
My suggestion will be to use a static member function of the class to retrieve the contents of the file from disk and construct an object after the contents have been retrieved successfully.
Instead of:
Abcd(QFile &src) :
Use
static Abcd deserialize(QFile& src);
and implement it as:
Abcd Abcd::deserialize(QFile& src)
{
long rX;
long rY;
long count;
if(src.read((char *)&rY, sizeof(rY)) != sizeof(rY)) throw false;
if(src.read((char *)&rX, sizeof(rX)) != sizeof(rX)) throw false;
if(src.read((char *)&count, sizeof(count)) != sizeof(count)) throw false;
return Abcd(rX, rY, count):
}
PS It's strange that you save _rY first and then _rX. There is nothing wrong, it's just strange.
My suggestion is to split up the logic of Abcd and serialization/deserialization into two classes.
Benefits:
no field _healthy as object is always valid by design.
class Abcd does only one job. Is free from any logic of storing (Single responsibility)
Few hints:
RVO is mandatory since c++ 17
const fields just make the object not copy/move assignable (unable to use with containers etc.). Simply properly use const correctness to ensure immutability.
do not inherit implementation, only interfaces: Abcd is final, no virtual methods - better performance.
follow the Cpp Core Guidelines
class Abcd final
{
public:
Abcd(const long refX, const long refY, const long count)
: _rX(refX)
, _rY(refY)
, _count(count)
{
}
long GetRX() const
{
return _rX;
}
long GetRY() const
{
return _rY;
}
long GetCount() const
{
return _count;
}
protected:
long _rX;
long _rY;
long _count;
};
#include <boost/optional.hpp>
#include <QFile>
template <typename T>
using Opt = boost::optional<T>; // or equivalent
// Choose better name for Serializer or even split it up
class AbcdSerializer final
{
public:
AbcdSerializer(QFile& file)
: _file(file)
{
}
// You may also throw an exception instead of returning optional
Opt<Abcd> TryDeserializeAbcd()
{
long rX;
long rY;
long count;
if (ReadValue(rY) && ReadValue(rX) && ReadValue(count))
{
return Abcd(rX, rY, count);
}
return {};
}
bool SerializeAbcd(const Abcd& abcd)
{
return WriteValue(abcd.GetRY()) && WriteValue(abcd.GetRX()) && WriteValue(abcd.GetCount());
}
private:
template <typename T>
bool ReadValue(T& value)
{
constexpr auto ValueSize = sizeof(value);
return _file.read(reinterpret_cast<char*>(&value), ValueSize) != ValueSize;
}
template <typename T>
bool WriteValue(const T& value)
{
constexpr auto ValueSize = sizeof(value);
return _file.write(reinterpret_cast<const char*>(&value), ValueSize) != ValueSize;
}
QFile& _file;
};
I made a bidirectional and 2-dimensional linked list. My nodes are called chunks, and they contain a pointer to the chunks on their left, right, bottom and top.
class chunk;
typedef std::shared_ptr<chunk> chunk_ptr;
typedef std::weak_ptr<chunk> chunk_wptr;
class chunk
{
public:
chunk(wanted_id) : id(wanted_id) {}
chunk_ptr left() const { return _left.lock(); }
chunk_ptr right() const { return _right.lock(); }
chunk_ptr top() const { return _top.lock(); }
chunk_ptr bottom() const { return _bottom.lock(); }
void left(const chunk_ptr set) { _left = set; }
void right(const chunk_ptr set) { _right = set; }
void top(const chunk_ptr set) { _top = set; }
void bottom(const chunk_ptr set) { _bottom = set; }
int id() const { return _id; }
private:
chunk_wptr _left, _right, _top, _bottom;
int _id;
void id(const int id) { _id = id; }
};
Now, let's imagine that I have built the following structure:
If I want to navigate from 1 to 4, I could use the following line of code:
id4 = id1->right()->right()->bottom();
Now let's imagine that chunk 3 has been removed, e.g. id2->right == id4->top == nullptr:
If I want to access id4 then to perform some operation on it, there will be a runtime error. To avoid to perform a check at each step, I would like to introduce a neutral chunk element:
auto null_chunk = std::make_shared<chunk>(-1); // Let's define its id as -1
null_chunk->left(null_chunk);
null_chunk->right(null_chunk);
null_chunk->top(null_chunk);
null_chunk->bottom(null_chunk);
Thus, the following statement would run succesfully:
id4 = id1->right()->right()->bottom();
And then id4 == null_chunk.
However, I'm not quite sure about how to integrate such an element in my code.
I could use a static variable:
// This is a public static method
chunk_ptr chunk::null_chunk()
{
static auto ptr = instanciate_null_chunk();
return ptr;
}
// This is a private static method
chunk_ptr chunk::instanciate_null_chunk()
{
auto ptr = std::make_shared<chunk>(-1);
ptr->left(ptr);
ptr->right(ptr);
ptr->top(ptr);
ptr->bottom(ptr);
return ptr;
}
Now, I would like to initialize left, right, top and bottom by null_chunk in my constructor:
chunk(wanted_id) : id(wanted_id)
{
this->left(null_chunk());
this->right(null_chunk());
this->top(null_chunk());
this->bottom(null_chunk());
}
This leads to a a recursion stack overflow (null_chunk calling the constructor calling null_chunk etc...).
This forces me to define a specific private constructor for null_chunk(), but because I'm using shared pointers, my constructor must be public to use make_shared...
Thus, there is a design flow. What would be the best way to implement such a feature?
One possible to solution to implement the null node is to use a static member. This member is initialized once using another static function, that creates a shared pointer with the null chunk and redirects all outgoing connections to the chunk itself.
On construction of any other chunk all outgoing connections point to the null chunk as well.
As mentioned in the comments above, make sure not to leak any memory due to circular references.
You have to create a second constructor as you mentioned. However using a private struct as argument prevents any calls to this constructor from outside the class.
class chunk {
public:
using chunk_ptr = std::shared_ptr<chunk>;
using chunk_wptr = std::weak_ptr<chunk>;
private:
int _id;
chunk_wptr _left, _right, _top, _bottom;
static chunk_ptr nullchunk;
struct pctor {};
static chunk_ptr gennull() {
chunk_ptr pnullchunk {std::make_shared<chunk>(pctor{})};
pnullchunk->_left = pnullchunk;
pnullchunk->_right = pnullchunk;
pnullchunk->_top = pnullchunk;
pnullchunk->_bottom = pnullchunk;
return pnullchunk;
}
public:
chunk(pctor) : _id(-1) {}
chunk(int id) : _id(id),
_left(chunk::nullchunk),
_right(chunk::nullchunk),
_top(chunk::nullchunk),
_bottom(chunk::nullchunk) {}
bool isNullNode() const
{ return this == chunk::nullchunk.get(); }
//
// Further functions omitted
//
};
chunk::chunk_ptr chunk::nullchunk {chunk::gennull()};
I'm doing this:
template<typename T> class var_accessor {
public:
std::set<std::shared_ptr<T>> varset;
std::map<std::string,std::shared_ptr<T>> vars_by_name;
std::map<uint32,std::shared_ptr<T>> vars_by_id;
std::shared_ptr<T> operator[](const uint32& index) { return vars_by_id[index]; }
std::shared_ptr<T> operator[](const std::string& index) { return vars_by_name[index]; }
bool is_in_set(std::shared_ptr<T> what) { auto it = varset.find(what); if (it == varset.end()) return false; return true; }
bool is_in_set(uint32 what) { auto it = vars_by_id.find(what); if (it == vars_by_id.end()) return false; return true; }
bool is_in_set(std::string& what) { auto it = vars_by_name.find(what); if (it == vars_by_name.end()) return false; return true; }
bool place(std::shared_ptr<T> what, const uint32 whatid, const std::string& whatstring) {
if (is_in_set(what)) return false;
varset.emplace(what);
vars_by_name.emplace(whatstring,what);
vars_by_id.emplace(whatid,what);
return true;
}
};
Then...
class whatever {
std::string name;
std::function<int32()> exec;
};
And:
class foo {
public:
var_accessor<whatever> stuff;
};
This works:
std::shared_ptr<whatever> thing(new whatever);
thing->name = "Anne";
thing->exec = []() { return 1; }
foo person;
person.stuff.emplace(thing, 1, thing->name);
Getting the name crashes it:
std::cout << person.stuff[1]->name;
But if I change the operator[]'s to return references, it works fine.
I don't want to be able to accidentally add new elements without adding to all 3 structures, so that's why I made
std::shared_ptr<T> operator[]
instead of
std::shared_ptr<T>& operator[]
Is there any way to prevent assignment by subscript but keep the subscript operator working?
To be clear I want to be able to keep doing
std::cout << person.stuff[4];
But NOT be able to do
std::shared_ptr<whatever> bob(new whatever);
bob->name = "bob";
person.stuff[2] = bob;
The error is a EXC_BAD_ACCESS inside the std::string class madness
Everything I read says simply "don't return references if you want to prevent assignment" but it also prevents using it for me.
Yes I know some things should be made private but I just want to get it working first.
Using Clang/LLVM in XCode 5.1
Thanks!
You should return a const reference. See this question
A const reference means the caller is not allowed to change the value, only look at it. So assignment will be a compile-time error. But using it will work (and be efficient).
Say I have a class with a couple of data members, and I want a class method that returns one, and the next time it is called returns the value of the other. Something like:
class MyClass
{
public:
MyClass():switch(0){};
int get();
private:
int intA, intB;
int sw;
};
int MyClass::get()
{
if ( (++sw)%2 )
return intA;
else
return intB;
}
What would a more elegant way of doing it be? I don't like the if...else statement very much. It's fine for something like return, but if I'm actually using more complex operations, I end up duplicating a ton of code. Or having to create a second method within each method that is called after I resolve what element I'm pointing to.
What I'd prefer to do, ideally, is to use some form of pointer, so I can do
class MyClass
{
public:
MyClass():switch(&intA){};
int get();
void toggleSwitch();
private:
int intA, intB;
int * sw;
};
int MyClass::get()
{
return *sw;
}
void MyClass::toggleSwitch()
{
if ( sw == &intA )
sw = &intB;
else
sw = &intA;
}
Or something to that effect. I could call toggleSwitch(), and have my class operate on either one or the other value easily.
I still don't like it though. I prefer to avoid if's when possible, and I shouldn't need one in this case. This use of a naked pointer should be pretty safe, but I was thinking I could have something like std::unique_ptr holding each element and then std::swap them. But then the pointers would own the elements, and they'd be dynamic memory instead.
So is there a better way to do it?
Well, switch is a keyword, but I'll roll with it. How about an array of pointers?
int *fields[] = {&intA, &intB};
int MyClass::get()
{
return *fields[++switch % 2];
}
This would expand nicely if you could have additional variables later.
Or maybe:
int MyClass::get()
{
return *fields[switch = 1 - switch];
}
If you return a reference then you could use get() internally.
int &MyClass::get()
{
return *fields[switch = 1 - switch];
}
I would encapsulate the concept of a toggling value:
template<typename T>
class Toggleable {
T first;
T second;
T* current;
T* other;
public:
Toggleable(const T& first, const T& second)
: first(first),
second(second),
current(&first),
other(&second) {
}
bool toggle() {
std::swap(current, other);
}
const T& get() const {
return *current;
}
}
Then use as:
class MyClass
{
Toggleable<int> value;
public:
MyClass()
: value(42, 1729)
{
}
const int& get() {
value.toggle();
return value.get();
}
};
I have defined the classes 'Outcome' and 'Bin'.
I am trying to pass an array of type Outcome to a Bin Constructor, in order to add each element of that array to a set of 'Outcome's that is a member property of the Bin Class.
//Bin.h
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
Bin(Outcome Outcs[], int numberofelements);
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
//In Bin.cpp
Bin::Bin(Outcome outcs[], int numberofelements) {
int i;
for (i=0;i<(numberofelements-1);i++) {
outcomeset.insert(outcs[i]); //When this LIne is commented out, no compile errors!
}
}
This results in a whole mess of errors in VS2010 that link back to library files. I have been unable to find anything online or in my "The Big C++" textbook. Is this a completely wrong implementation of this sort of functionality? Or am I missing something rather basic?
For the curious I am implementing this as part of the 'Roulette' Problem from this free textbook http://www.itmaybeahack.com/homepage/books/oodesign.html
Thanks for your help!
EDIT: I have added the (rather lengthy) error text to a pastebin, here: http://pastebin.com/cqe0KF3K
EDIT2: I have implemented the == != and < operators for the outcome class, and the same line still does not compile. Here are the implementations
//Outcome.cpp
bool Outcome::operator==(Outcome compoutc) {
if (mEqual(compoutc) == true) {
return true;
}
else {
return false;
}
}
bool Outcome::operator!=(Outcome compoutc) {
if (mEqual(compoutc) == false) {
return true;
}
else {
return false;
}
}
bool Outcome::operator<(Outcome compoutc) {
if (odds < compoutc.odds) {
return true;
}
else {
return false;
}
}
EDIT3: Implemented the comparison operator with the de-referenced parameter and const tags and now it compiles!
You need to define an operator< for the class being inserted into the set.
Also note that instead of an explicit loop, you're probably better off using a pair of "iterators" (pointers, in this case) and actually initializing the set:
#include <set>
#include <string>
class Outcome {
int val;
public:
bool operator<(Outcome const &other) const {
return val < other.val;
}
Outcome(int v = 0) : val(v) {}
};
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
// Actually initialize the set:
Bin(Outcome Outcs[], int n) : outcomeset(Outcs, Outcs+n) {}
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
int main() {
// Create an array of Outcomes
Outcome outcomes[] = {Outcome(0), Outcome(1) };
// use them to initialize the bin:
Bin b((outcomes),2);
return 0;
}