const correctness for configuration structures - c++

I have a configuration file which gets read in, parsed and put into structures at the beginning of my programs run time.
The problem I am having is that I want these structures to be constant since the values in them should not change during the programs lifespan.
Currently I am doing the following:
config.h
#pragma warning(push)
#pragma warning(disable: 4510) /*-- we don't want a default constructor --*/
#pragma warning(disable: 4610) /*-- we don't want this to ever be user instantiated --*/
typedef struct SerialNode {
private:
void operator=(SerialNode&);
public:
const char* const port;
const char* const format;
} SerialNode;
#pragma warning(pop)
typedef std::map<const char*, const SerialNode*, MapStrComp> SerialMap;
SerialMap SerialConfig;
config.cpp
/*-- so we don't fall out of scope --*/
SerialNode* global_sn;
SerialNode local_sn = {port, format};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
This works fine. However my problem is that now I am dealing with more complicated configuration data which requires me to pull a structure back out of the list, modify it and then put it back.
Obviously I can't modify it, so the solution would be something like:
SerialNode* global_sn;
SerialNode* old_sn = SerialConfig[key_store];
SerialNode local_sn = {port, format, old_sn->old_data, old_sn->more_old_data};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
delete old_sn;
But this strikes me as bad programming practice. Is there is a better way to achieve what I'm going for which doesn't require such a hacked looking solution?
For reference, I'm using Visual Studio 2010

As always, the best thing you can do is not re-implement something that has already been written. There are a large number of libraries and frameworks that will help with serialization for c++:
Boost Serialization
Qt
Protocol Buffers
msgpack
Capn' Proto
Ideally the serialization framework you choose will exactly recreate the data graph that you are trying to store. Regardless of whether you have done any fixup, your goal will likely be to only provide const access to the global configuration data. Just make sure that mutators (including non const pointers) are not exposed via a header file.

The simple answer is what Thomas suggest, but correctly done (that is, not causing undefined behavior):
Create a mutable configuration object but pass it to the rest of the components by constant reference. When you create (and where you maintain) the real object you can change it, but the rest of the application won't be able to modify the config. A common pattern I have used in the past was:
class SomeObject {
Configuration const & config;
public:
SomeObject(Configuration const & config) : config(config) {}
void f() {
if (config.someParam()) { ...
// ...
void loadConfiguration(Config & config) { ... }
int main() {
Configuration config;
loadConfiguration(config); // config is a non-const &, can modify
SomeObject object(config); // object holds a const&, can only read
object.f();
// ...

This is not an answer to your question, just some observations to your code.
You don't need the typedef struct SerialNode { ... } SerialNode;, this is a c idiom. In c++, you just write struct SerialNode { ... }; and use SerialNode as a type name.
If you want to prevent a default constructor, make it private as you already do with the assignment operator
class SerialNode {
private:
SerialNode();
SerialNode &operator=(SerialNode&);
...
};
Don't use char* members, use std::string instead. C++ strings are much easier and safer to use than plain char pointers and the associated heap allocation.
Same goes for the map key; if you use std::string as a key, you don't need MapStrComp anymore, because std::string already provides an appropriate comparison.

Probably nicer is to wrap the whole thing in a singleton class:
class Config {
public:
static Config const& get() { return *config; }
static void load();
SerialNode const* operator[](const char*);
private:
static Config* config;
SerialMap map;
};
void Config::load() {
config = new Config();
// put things into it
}
Disclaimer: not tested, and haven't used C++ in a while, so there might be some syntax errors :)

Related

How do I assign to a const variable using an out parameter in C++?

In a class header file Texture.h I declare a static const int.
static const int MAX_TEXTURE_SLOTS;
In Texture.cpp I define the variable as 0.
const int Texture::MAX_TEXTURE_SLOTS = 0;
Now in Window.cpp class's constructor I attempt to assign to the variable using an out parameter, however this obviously does not compile as &Texture::MAX_TEXTURE_SLOTS points to a const int* and not an int* .
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &Texture::MAX_TEXTURE_SLOTS);
I have tried using const_cast, but am greeted with a segmentation fault on runtime.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, const_cast<int*>(&Texture::MAX_TEXTURE_SLOTS));
I have also tried directly casting to an int * but once again, seg fault.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (int*)&Texture::MAX_TEXTURE_SLOTS);
Many thanks.
EDIT 2: So since you're trying to abstract OpenGL contexts, you'll have to let go of the "traditional" constructor/destructor idioms. And just for your information (unrelated to this question): OpenGL contexts are not tied to windows! As long as a set of windows and OpenGL contexts are compatible with each other, you may mix and match any way you like. But I digress.
The standard idiom to deal with a situation like yours is to use preinitializing factory functions. Like this:
class MyOpenGLContextWrapper {
public:
// Yes, shared_ptr; using a unique_ptr here for objects that are kind
// of a nexus for other things -- like an OpenGL context -- just creates
// a lot of pain and misery. Trust me, I know what I'm talkink about.
typedef std::shared_ptr<MyOpenGLContextWrapper> ptr;
struct constdata {
NativeGLContextType context;
// ...
GLint max_texture_image_units;
// ...
};
static ptr create();
protected:
MyOpenGLContextWrapper(constdata const &cdata) : c(cdata) {};
virtual ~MyOpenGLContextWrapper();
constdata const c;
}
MyOpenGLContextWrapper::ptr MyOpenGLContextWrapper::create()
{
struct object : public MyOpenGLContextWrapper {
object(MyOpenGLContextWrapper::constdata const &cdata) : MyOpenGLContextWrapper(cdata) {}
~object(){}
};
MyOpenGLContextWrapper::constdata cdata = {};
// of course this should all also do error checking and failure rollbacks
cdata.context = create_opengl_context();
bind_opengl_context(cdata.context);
// ...
glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, &cdata.max_texture_image_units);
return std::make_shared<object>(cdata);
}
EDIT: I just saw that you intend to use this to hold on to a OpenGL limit. In that case you can't do this on a global scope anyway, since those values depend on the OpenGL context in use. A process may have several OpenGL contexts, each with different limits.
On most computer systems you'll encounter these days, variables declared const in global scope will be placed in memory that has been marked as read only. You literally can't assign to such a variable.
The usual approach to implement global scope runtime constants is by means of query functions that will return from an internal or otherwise concealed or protected value. Like
// header.h
int runtime_constant();
#define RUNTIME_CONSTANT runtime_constant()
// implementation.c / .cpp
int runtime_constant_query(){
static int x = 0;
// NOTE: This is not thread safe!
if( !x ){ x = determine_value(); }
return x;
}
You can then fetch the value by calling that function.
Provided that glGetIntegerv doesn't depend on other gl* functions being called before, you may use an immediately-invoked lambda:
// Texture.cpp
const int Texture::MAX_TEXTURE_SLOTS = []
{
int maxTextureSlots{0}:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureSlots);
return maxTextureSlots;
}();
You don't.
You can't assign to a const outside of its definition. Also, using a const variable where the const has been const_casted away is UB. This also means you can't directly initialize a const variable with an output parameter. For trivial types, just output to another variable and make a const copy if you so wish.
If you were the author of the function you're calling, you would do well not to use out parameters, and then you could assign to const variables directly, perhaps using structured bindings if you want to name multiple of the outputs at a time. But here, you're not.

Efficient way of storing a large amount of character data between transactions in C++

For our application we have the following scenario:
Firstly, we get a large amount of data (on cases, this can be more than 100MB) through a 3rd party API into our class via a constructor, like:
class DataInputer
{
public:
DataInputer(int id, const std::string& data) : m_id(id), m_data(data) {}
int handle() { /* Do some stuff */ }
private:
std::string m_id;
std::string m_data;
};
The chain of invocation going into our class DataInputer looks like:
int dataInputHandler()
{
std::string inputStringFromThirdParty = GiveMeStringFrom3rdPartyMagic(); // <- 1.
int inputIntFromThirdParty = GiveMeIntFrom3rdPartyMagic();
return DataInputer(inputIntFromThirdParty, inputDataFromThirdParty).handle();
}
We have some control over how the dataInputHandler handles its string (Line marked with 1. is the place where the string is created as an actual object), but no control for what GiveMeStringFrom3rdPartyMagic actually uses to provide it (if it's important for anyone, this data is coming from somewhere via a network connection) so we need. As a consolation we have full control over the DataInputer class.
Now, what the application is supposedly doing is to hold on to the string and the associated integer ID till a later point when it can send to another component (via a different network connection) provided the component provides a valid ID (this is the short description). The problem is that we can't (don't want to) do it in the handle method of the DataInputer class, it would block it for an unknown amount of time.
As a rudimentary solution, we were thinking on creating an "in-memory" string store for all the various strings that will come in from all the various network clients, where the bottom line consists of a:
std::map<int, std::string> idStringStore;
where the int identifies the id of the string, the string is actually the data and DataInputer::handle does something like idStringStore.emplace(m_id, m_data);:
The problem is that unnecessarily copying a string which is on the size of 100s of megabytes can be a very time consuming process, so I would like to ask the community if they have any recommendations or best practices for scenarios like this.
An important mention: we are bound to C++11 for now :(
Use move-semantics to pass the 3rd-party data into your DataInputer constructor. The std::move here is redundant but makes the intention clear to the reader:
class DataInputer
{
public:
DataInputer(int id, std::string&& data) : m_id(id), m_data(std::move(data)) {}
int handle() { /* Do some stuff */ }
private:
std::string m_id;
std::string m_data;
};
And pass GiveMeStringFrom3rdPartyMagic() directly as an argument to the constructor without first copying into inputStringFromThirdParty.
int dataInputHandler()
{
int inputIntFromThirdParty = GiveMeIntFrom3rdPartyMagic();
return DataInputer(inputIntFromThirdParty, GiveMeStringFrom3rdPartyMagic()).handle();
}
Of course, you can use a std::map or any other STL container that supports move-semantics. The point is that move-semantics, generally, is what you're looking to use to avoid needless copies.

Standard way to handle the encapsulated access to values stored in private map without breaking the abstraction in C++

I want to create a class in order to manage markup language (such as HTML) in C++. I would like my class to retain attributes and sub-tags. The problem is, given encapsulated containers, how to properly abstract the accesses and what to return in order to provide an easy way to check if the value returned is valid.
I defined my class containing two maps as private members (nominally, std::map<std::string, Tag> _children; and std::map<std::string, std::string> _attr;. I defined two functions to populate these fields and I would like to define two functions to read-access the stored elements.
The problem is, I don't want to break my abstraction and, as I'm doing this in order to work on my c++ skills, I would like to find the proper way (or cleaner way, or standard way) to do it.
One basic solution would be to simply call return map.find(s);, but then I would have to define the return type of my function as std::map<std::string, Tag>::const_iterator, which would break the abstraction. So I could dereference the iterator returned by map.find(), but in case the value in not in the map I would dereference a non-dereferencable iterator (_children.cend()).
What I defined so far:
using namespace std;
class Tag {
static const regex re_get_name, re_get_attributes;
string _name;
map<string,string> _attr;
map<string,Tag> _children;
public:
Tag(const string &toParse) {
/* Parse line using the regex */
}
const string& name() const {
return _name;
}
Tag& add_child(const Tag& child) {
_children.insert(child._name, child);
return *this;
}
SOMETHING get_child(const string& name) const {
map<string,Tag>::const_iterator val = _children.find(name);
/* Do something here, but what ? */
return something;
}
SOMETHING attr(const string& name) const {
map<string, string>::const_iterator val = _attr.find(name);
/* Do something here, but what ? */
return something;
}
};
const regex Tag::re_get_name("^<([^\\s]+)");
const regex Tag::re_get_attributes(" ([^\\s]+) = \"([^\\s]+)\"");
What would be the proper way to handle this kind on situation in C++? Should I create my own Tag::const_iterator type? If so, how to? Should I go for a more "C" approach, where I just define the return type as Tag& and return NULL if the map doesn't contain my key? Should I be more OOP with a static member static const Tag NOT_FOUND, and return a reference to this object if the element isn't in my map? I also thought of throwing an exception, but exception management seems to be quite heavy and ineffective in C++.
std::optional could help you, but needs a C++17 ready standard library, so in the meantime you could also use boost::optional which is more or less the same, since AFAIK std::optionals design was based on the boost one. (As boost is often the source for new C++ standard proposals)
Even as I am reluctant to make you a proposal because of the general problem of your approach, I still wrote one for you, but please consider the points after the code:
#include <string>
#include <regex>
#include <map>
#include <boost/optional.hpp>
class Tag {
static const std::regex re_get_name, re_get_attributes;
using string = std::string;
string _name;
std::map<string,string> _attr;
std::map<string,Tag> _children;
public:
Tag(const string &toParse) {
/* Parse line using the regex */
}
const string& name() const {
return _name;
}
Tag& add_child(const Tag& child) {
_children.emplace(child._name, child);
return *this;
}
boost::optional<Tag> get_child(const string& name) const {
auto val = _children.find(name);
return val == _children.cend() ? boost::optional<Tag>{} : boost::optional<Tag>{val->second};
}
boost::optional<string> attr(const string& name) const {
auto val = _attr.find(name);
return val == _attr.cend() ? boost::optional<string>{} : boost::optional<string>{val->second};
}
};
As you can see you are basically just reimplementing container semantics of std::map but also with the somehow built in parser logic. I strongly disagree from this approach, since parsing gets ugly very fast in a hurry, and mixing value generation code into a container which could i.e. should be use as a value class will make things even worse.
My first suggestion is to just declare/use your Tag class/struct as a value class, so just containing the std::maps as public members. Put your parsing functions in a namespace along with the Tag container, and let them just be functions or distinct classes if needed.
My second suggestion is small one: Don't prefix with _, it's reserved and considered bad style, but you can use it as a suffix. Also don't use using namespace directives outside of a class/function/namespace block i.e. global, it's bad style in a .cpp, and extremely bad style in a header /.h/.hpp
My third suggestion: Use the boost spirit qi parser frame work, you would just declare your value classes as I suggestion first, while qi would automatically fill them, via boost fusion. If you know the EBNF notation already, you can just write the EBNF like grammar in C++, and the compiler will generate a parser via template magic. However qi and especially fusion has some issues, but it makes things much easier in the long run. Regexes only does half of the parsing logic, at best.

variable global const "macros" in C++ and optimal design patterns

I inherited some 10 year old code I have to complete. The code is in MFC (C++).
There's a .h file where the custom data structures are written and some const variables are in there as Globals. Some of these are used for MS Office file extensions, of type CString, and are declared as _T(".doc"), _T(".xls"), etc.
Obviously these are dated and need to be updated to recognize the Office 2007 and later extensions. My first brilliant idea was to use const_cast to change the constant if needed, but found out later that's a no-no and resulted in undefined behavior (sometimes it would switch back to .doc).
I then decided to create a struct and have two structs inherit from it. I created a void method in the base struct to make it abstract but otherwise it does nothing. Here's the code:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
eOfficeExtensions(CString word, CString excel, CString wordpad, INT ver) :
WORD_EXTENSION(word), EXCEL_EXTENSION(excel), WORDPAD_EXTENSION(wordpad), EXTENSION2007(ver){}
//method to ensure base class is abstract
virtual void Interface() = 0;
};
struct eOfficeExtensions2003 : public eOfficeExtensions{
public:
eOfficeExtensions2003() : eOfficeExtensions(_T(".doc"), _T(".xls"), _T(".rtf"), 0){}
private:
virtual void Interface(){}
};
struct eOfficeExtensions2007OrLater : public eOfficeExtensions{
eOfficeExtensions2007OrLater() : eOfficeExtensions(_T(".docx"), _T(".xlsx"), _T(".rtf"), 1){}
private:
virtual void Interface(){}
};
This feels like a ridiculous amount of code for what should be a simple conditional definition. What would an experienced programmer do?
EDIT
These constants should only be set once and never changed. The version of MS Office installed is determined by scanning registry subkeys in a class that deals with memory management.
The constants are mainly used to create new files or search a directory for files with that extension, not for resolving conditional statements. The struct should also be instantiated once as a eOfficeExtensions* pointer to the relevant child struct.
Your inheritance tree essentially defines two different values for the base struct.
You don't need inheritance just to define those values, you only need two variables:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
};
const eOfficeExtensions extensions2003{_T(".doc"), _T(".xls"), _T(".rtf"), 0};
const eOfficeExtensions extensions2007{_T(".docx"), _T(".xlsx"), _T(".rtf"), 1};
const eOfficeExtensions* extensions = 0;
// ... Later ...
if (office2007Installed)
extensions = &extensions2007;
else
extensions = &extensions2003;

Nested Classes C++ static inner methods (Xml parsing and trying to populate vector with values)

So this is what I am trying to accomplish. I am trying to use a sax parser to parse some XML. it looks like I need to call all their methods as statics. So if I want to pass a value back from say startElement it is static void startElement. Which brings me to my example code. I have been pulling my hair on how to update a value in a Nesting class from a static member function.
I have looked at several things such as defining OuterClass * oc; then trying to reference oc->allRecords, but since it is a static method inside, it fails. I am sure I am doing something wrong architecturally, so any feedback on what would be the right way to do this would be a great help. Thanks.
class Attribute {
string AttributeName;
string AttributeValue;
};
typedef shared_ptr<Attribute> AttributePtr;
class AttributeSet {
vector<AttributePtr> Attributes;
};
typedef shared_ptr<AttributeSet> AttributeSetPtr;
class OuterClass {
public :
vector<AttributeSetPtr> allRecords;
class InnerClass {
public:
static mymethod1() {
// I need to be able to set attributes here :
// This would be the characters method for sax parsing
// What is the right way to Attributes.push_back(new Attribute(Name,Value));
}
static mymethod2() {
// I also need to be able to add Records here :
// This would be the endElement for sax parsing
// What is the right way to allRecords.push_back(AttributeSet);
}
};
// EDIT: CALLING CODE GOES HERE (WAS EDITED - SEE BELOW)
};
// ADDING INFORMATION REGARDING HOW METHOD 1 & 2 are called
xmlSAXHandler saxHandler;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.initialized = XML_SAX2_MAGIC;
...
saxHandler.endElementsNs = &InnerClass::method2;
saxHandler.characters = &InnerClass::method1;
...
InnerClass innerXmlParsingClass
xmlSaxUserParseMemory( &saxHandler, &innerXmlParsingClass, xmlString, xmlString.length());
Your mistake is using an inner class (are you coming from Java?).
I don't know what you believe you are are achieving with an inner class, but it won't work. Don't use inner classes in C++ unless you really know what it does (for inner classes, protected and private members of the outer classes are seen as if they were public).
Now, as the solution to your problem, I guess it depends on the implementation you're using (I used once Apache's Xerces SAX, but I know Microsoft offers its own SAX implementation, and that there should be a lot other alternatives, so...)
Edit
After the comment, I found the following tutorial:
http://www.jamesh.id.au/articles/libxml-sax/libxml-sax.html
I must say that, coming from Java to C++, and using a C API, you have a kind of courage...
:-D
If you are not familiar enough with function pointers, and C in general, using libxml2 will be a challenge. Be sure that in the end, you will understand those notions... Note that C have a way to handle the data that C++, Java or C# developers associate to this. The C way is to pass a pointer to your data (the user data) to a function, and when the callback is called, it passes back this pointer, typed as a void *. You must then cast it back to its right type, and voilà, you have your this back.
:-)
Anyway, reading the doc, I see that when you parse the file, you'll call the following C function:
int xmlSAXUserParseFile( xmlSAXHandlerPtr sax,
void * user_data,
const char * filename);
the user_data part is the one that interest you because it enables you to have a context. So, wrapping this function in a C++ class, you could have something like:
// MySaxBase.hpp
class MySaxBase
{
public :
MySaxBase() ;
int parseFile(const std::string & p_filename) ;
virtual void startDocument() ;
virtual void endDocument() ;
private :
static void do_startDocument(void *p_user_data) ;
static void do_endDocument(void *p_user_data) ;
xmlSAXHandler m_sax ;
}
.
// MySaxBase.cpp
extern "C"
{
void do_startDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->startDocument() ;
}
void do_endDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->endDocument() ;
}
} // extern "C"
MySaxBase::MySaxBase()
{
// the m_sax structure must be set to zero to NULL all its
// pointers to functions
memset(&m_sax, 0, sizeof(xmlSAXHandler)) ;
// Now, we initialize some pointers to the static method we
// want to be called
this->m_sax.startDocument = do_startDocument ;
this->m_sax.endDocument = do_endDocument ;
}
int MySaxBase::parseFile(const std::string & p_filename)
{
// the important thing, here, is the this pointer, passed as
// a user_data parameter
return xmlSAXUserParseFile(&m_sax, this, p_filename.c_str()) ;
}
void MySaxBase::startDocument()
{
// The document started. Override this method to
// actually do something
}
void MySaxBase::endDocument()
{
// The document ended. Override this method to
// actually do something
}
I did not test this, and I never used libxml2, but I guess the code must be Ok, and this should be enough for you to continue on your own: Just add the methods you want to support, initialize the sax handler with the relevant function pointers, and you'll have your class complete.
The MySaxBase::startDocument and MySaxBase::endDocument methods are virtual just for you to derive from MySaxBase and then override those methods.
Edit 2
I'll reproduce here Steve Jessop's excellent comment:
+1. One tiny quibble - I don't think that static member functions are guaranteed by the C++ standard to have C linkage / calling convention, but to use them as a callback from a C API, that's what they need. I don't specifically know what implementations it makes a difference, but for safety do_startDocument should be a free function declared with extern "C". On the same subject: a Java programmer may not realise you have make sure that the function can't throw an exception (because C doesn't have them). So you'd normally want to see a try/catch(...) in the wrapper function. – Steve Jessop
Following this, and after reading Johannes Schaub - litb (who else?) no less excellent answer at static vs extern "C"/"C++" , I modified the code to make do_startDocument and do_endDocument real C functions (i.e. wrapped in an extern "C" block). This usually is not important (I never encountered this kind of problem), but, better safe than sorry.
Your basic problem is that static methods are not per-instance, so there is no this pointer. You somehow need to get a OuterClass* passed to mymethod1 and mymethod2.
If you show us how mymethod1 and mymethod2 are called, we can help you further.
If it's simply called by you someplace where you have a OuterClass object, then your solution is simple:
class OuterClass
{
// ...
static void mymethod1(OuterClass* oc)
{
oc->all_records.push_back( something );
}
};
void some_func()
{
OuterClass oc;
OuterClass::method1(&oc);
}
Since you updated your question here is how you should do this:
class OuterClass {
public:
vector<AttributeSetPtr> allRecords;
void characters(const xmlChar* ch, int len)
{
// do here whatever you want
allRecords.push_back(bla bla);
}
static void static_characters(void* ctx, const xmlChar* ch, int len) {
// retrieve this pointer from ctx
static_cast<OuterClass*>(ctx)->characters(ch, len);
}
};
saxHandler.characters = &OuterClass::static_characters;
...
OuterClass outerClass;
xmlSaxUserParseMemory(&saxHandler, static_cast<void*>(&outerClass), xmlString, xmlString.length());