Initialize static object graph - c++

I want to create a number of objects that hold constant data for an application.
I have got the following code until now:
class NodeObject;
class ComplexData
{
struct datum
{
Type type;
int value;
};
vector<datum> data;
vector<NodeObject*> nodeObjects;
public:
void addDatum(Type, int) const;
void addNodeObject(NodeObject*) const;
};
class NodeObject
{
int id;
string name;
ComplexData complexData;
NodeObject(string); // private
public:
static const NodeObject NODE_1;
static const NodeObject NODE_2;
static const NodeObject NODE_3;
};
const NodeObject NodeObject::NODE_1("Node 1");
const NodeObject NodeObject::NODE_2("Node 2");
const NodeObject NodeObject::NODE_3("Node 3");
However I'm not sure, how to put the more complex data into my nodes while keeping the single nodes constant. I think, I could drop the const keyword since members are private, but that doesn't really solve the problems. At the moment I use this very ugly aproach - I hope there are better ways to do so:
class NodeObject
{
// stuff like before ...
private:
static bool initialized;
static bool initialize();
};
bool NodeObject::initialize() {
// for example
NODE_1.complexData.addDatum(someType, 1);
NODE_3.complexData.addNodeObject(&NODE_1);
}
bool NodeObject::initialized = NodeObject::initialize();
Due to the fact that I don't need the bool variable afterwards I think it can be eliminated somehow.? Putting everything into the constructor might be possible but that will blow up the code too much.
Do ye have any suggestions?

Related

Modifying a data of type "static const int* const" from a member function

TLDR Question:
class MyClass
{
public:
void Modify()
{
//How can I modify MyData here
}
public:
static const int* const MyData;
};
Lore:
I have a class like this:
class Window
{
public:
const int* GetKeyboard()
{
return m_Keyboard;
}
private:
const int* const m_Keyboard = 0;
};
With this I would access keyboard as WindowObjectPtr->GetKeyboard() but I want to access it as Input::Keyboard. So I wrote something like this:
class Window
{
public:
const int* GetKeyboard()
{
return m_Keyboard;
}
private:
const int* const m_Keyboard = 0;
};
const int* Input::Keyboard = 0;
class Application;
class Input
{
friend class Application;
private:
static void SetKeyboard(const int* k) { Keyboard = k; }
public:
static const int* Keyboard;
};
class Application
{
public:
void Init()
{
Input::SetKeyboard(m_Window.GetKeyboard());
}
private:
Window m_Window;
};
int main()
{
Application application;
application.Init();
//Input::Keyboard
}
The only problem with the above code is that I can do Input::Keyboaord = nullptr;
So I want to change definition of keyboard to static const int* const Keyboard; but then Input::SetKeyboard cannot set it anymore.
Is there a valid version of something like mutable static const int* const Keyboard; ? or a different method of achieving what I am trying to do?
Either an object is const or it isn't. If it is const it must be given a value in its initialization and any attempt at changing it later will cause undefined behavior (if it isn't ill-formed to begin with).
There is no way to make an object const after a certain other point in the execution flow.
Of course you can just add a const reference to the object and use that whenever you don't intent to modify it for const-correctness:
static const int* Keyboard;
static const int* const& cKeyboard = Keyboard;
Now Keyboard can be used for modification and cKeyboard can't (without const_cast trickery).
But that all seems like completely avoidable and messy, since you could just have Keyboard be a non-static member, have Application have a non-static Input member and then have all initialization happen in the constructor's initializer lists. Then there wouldn't be a problem with having Keyboard be const-qualified at all.
Many things can be hacked.
For example you can have a constant static member which references a private non-static member. The private member can be initialized and set later by a friend. The public member can only be used to read:
#include<iostream>
struct foo {
static const int& x_public;
friend class bar;
private:
static int x_private;
};
const int& foo::x_public = foo::x_private;
int foo::x_private = 0;
struct bar {
bar() {
foo::x_private = 42;
}
};
int main() {
bar b;
std::cout << foo::x_public;
}
Thgouh, I am not really suggesting to use this. I agree with this answer that you should rather use a non-static member.

Proper way to populate map of member objects and store one member with a smart pointer using RAII

So I am pretty new to C++ and am trying to understand smart pointers and the RAII design pattern. My question is this: say I have an object that contains a map of objects. I want one object at a time to be active, that is a want a pointer that points to one of the objects from the map. What is a proper RAII way to go about it using smart pointers? Below is what I have tried so far.
//StateMachine.h
std::unique_ptr<GameObject> p1Paddle = std::make_unique<GameObject>(Paddle());
std::unique_ptr<GameObject> p2Paddle = std::make_unique<GameObject>(Paddle());
std::unique_ptr<GameObject> ball = std::make_unique<GameObject>(Ball());
//StateMachine.cpp
StateMachine::StateMachine()
{
gameObjects["p1Paddle"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(p1Paddle));
gameObjects["p2Paddle"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(p2Paddle));
gameObjects["ball"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(ball));
}
void StateMachine::ChangeState(std::string key)
{
activeObject = std::move(gameObjects[key]);
}
Instead of using map and smart-pointer and based on your requirements that you only want a single object type at a given moment of time, perhaps you want a priority queue based implementation instead...
Here's a pseudo implementation:
#include <algorithm>
#include <cstdint>
#include <queue>
#include <string>
#include <vector>
enum class ComponentType {
PADDLE,
BALL
};
class Component {
protected:
ComponentType type_;
uint32_t id_;
priority_;
Component(ComponentType type, uint32_t id, float priority)
: type_{type}, id_{id}, priority_{prioity};
public:
virtual ~Component() {}
auto type() const { return type_; }
auto id() const { return id_; }
auto priority() const { return priority_; }
void updatePriority(float newPriority) { priority_ = newPriority; }
};
class Paddle : public Component {
private:
std::string name_;
public:
Paddle(std::string_view name, float priority) :
Component(ComponetType::PADDLE, std::stoi(name.data()), priority),
name_{name}
{}
auto name() const { return name_; }
};
class Ball : public Component {
private:
std::string name_;
public:
Ball(std::string_view name, float priority) :
Component(ComponentType::BALL, std::stoi(name.data()), priority),
name_{name}
{}
auto name() const { return name_; }
};
class CmpFunc {
public:
int operator(){ const Component& a, const Component& b) {
return a.priority() > b.priority();
}
};
class Game {
private:
//std::vector<Component*> components_;
std::priority_queue<Component*, std::vector<Component*>, CmpFunc> priority_;
public:
void initialize() {
Paddle paddle1("paddle_1", 0.1f);
Paddle paddle2("paddle_2", 0.2f);
Ball ball("ball", 0.3f");
addComponent(&paddle1);
addComponent(&paddle2);
addComponent(&ball);
}
void addComponent(Component* component) {
if (component == nullptr)
throw std::runtime_exception( "invalid component pointer!" );
//components_.push_back(component);
priority_.push(component);
}
auto getComponent() {
if (!priority_.empty()) {
auto component = priority_.top();
priority_.pop();
/*components_.erase(
std::remove(components_.begin(), components_.end(), component),
components_.end()
);*/
return component;
}
return nullptr;
}
};
This is just a pseudo example code to show a priority queue... I didn't show any implementation of updating or changing the priority queue of an object, nor did I show, how to directly use it based on some state X of the game or finite-state-machine... That would be an exercise for you...
I can not say whether this code will compile and run since I typed it out right here and have not yet tested it hence the pseudo code. You can play around with it and try to get it to compile and from there expand it to fit your own needs...

C++ large string initialization and use

Hi I have an array of around 500 strings. Multiple functions in my class use this variable. I obviously do not want to initialize that array multiple times throughout my program. What would be the most efficient method to initialize it once and be able to use it throughout the class?
Here is an example of what I mean:
SomeClass.h:
class SomeClass {
public:
static const std::string large_list[];
private:
void someFunc();
void someFunc2();
void someFunc3();
}
SomeClass.cpp:
void SomeClass::someFunc1(){
static std::string large_list[] = {"something", "somethingelse", "somethingelse1"...};
//do something with the large_list
}
void SomeClass::someFunc2(){
static std::string large_list[] = {"something", "somethingelse", "somethingelse1"...};
//do something with the large_list
}
void SomeClass::someFunc3(){
static std::string large_list[] = {"something", "somethingelse", "somethingelse1"...};
//do something with the large_list
}
Thanks.
You can use the following in-class initialization (note I didn't use std::string since it's constructor is not constexpr):
class SomeClass {
public:
static constexpr const char* large_list[] = {"something", "somethingelse", "somethingelse1"};
};

Recasting const function

I'm using a library (libtcod) that has an A* pathfinding algorithm. My class inherits the callback base class, and I implement the required callback function. Here is my generic example:
class MyClass : public ITCODPathCallback
{
...
public: // The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() { // non-const stuff }
};
I found a number of examples using const_cast and static_cast, but they seemed to be going the other way, making a non-const function be able to return a const function result. How can I do it in this example?
getWalkCost() is defined by my library that I cannot change, but I want to be able to do non-const things in it.
The best solution depends on why you want to do non-const stuff. For example, if you have a cache of results that you want to use to improve performance, then you can make the cache be mutable, since that preserves the logical constness:
class MyClass : public ITCODPathCallback
{
...
public: // The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() const { // ok to modify cache here }
mutable std::map<int,int> cache;
};
Or perhaps you want to record some statistics about how many times the getWalkCost was called and what the maximum x value was, then passing a reference to the statistics may be best:
class MyClass : public ITCODPathCallback
{
...
public:
struct WalkStatistics {
int number_of_calls;
int max_x_value;
WalkStatistics() : number_of_calls(0), max_x_value(0) { }
};
MyClass(WalkStatistics &walk_statistics)
: walk_statistics(walk_statistics)
{
}
// The callback function
float getWalkCost(int xFrom, int yFrom, int xTo, int yTo, void *userData ) const
{
return this->doSomeMath();
};
float doSomeMath() const { // ok to modify walk_statistics members here }
WalkStatistics &walk_statistics;
};
You can hack it this way:
return const_cast<MyClass*>(this)->doSomeMath();
Of course this won't be considered good design by most people, but hey. If you prefer you can instead make doSomeMath() const, and mark the data members it modifies as mutable.

How to pass constant arrays to constructor initializer lists

I have a message class that I decided to use the builder design pattern. Each message, when completely built, looks very similar. I use a std::string to hold the information (its actually just independent chars, so I could have used vector<char> but the .c_str() was convenient.
The method of construction of each different subtype of message is the same (build header, build cargo, build footer, calc checksum... this is defined in the MessageBuilder class (and inherited to custom message builder classes):
class MessageBuilder
{
public:
// implementation details for all messages
static const int32 MsgDelimeter = 99;
// ...
Message getMsg();
void buildMessage();
protected:
MessageBuilder(uint8 msgID, uint8 cargoLen, uint8 csi, const uint8* cargo, const uint8 length)
: m_msgID(msgID), m_cargoLen(cargoLen), m_csi(csi),
m_cargo(cargo), m_contents(""), m_msg(m_contents)
{ }
// I previously tried passing cargo and length as just a std::string
// if I could get that to work it would also be fine
void buildHeader();
void buildCargo();
void buildFooter();
void resizeContents();
void calculateCheckSum();
// message is built in m_contents
Message::string m_contents;
Message::string m_cargo;
Message m_msg;
// variables specific to msg type
uint8 m_msgID;
uint8 m_cargoLen;
uint8 m_csi;
private:
};
Then to build a specific message, I have a specific class:
class CustomMessageABuilder : public MessageBuilder
{
public:
static const uint8 CustomMessageAID = 187;
// more details
// ...
// what I want to do
// static const uint8 CustomMessageACargo[4] = {0x65, 0xc7, 0xb4, 0x45};
// ** HERE **
CustomMessageABuilder ()
: MessageBuilder(CustomMessageAID,
CustomMessage1CargoLen,
//...
CustomMessageACargo,
CustomMessageALength
{ }
};
Anyway, what I want to do is pass the only custom string of characters, the cargo, from the CustomMessageABuilder constructor to the MessageBuilder class, where it will be stored in the middle of the message.
The cargo is different for each message, but gets stored in the same way, so all the logic for storing it/creating the cargo is in the base MessageBuilder class. All the differences, like msgID, cargoLen, cargo, ... are constants in the CustomMessageBuilder classes.
This would allow me to keep my message class really simple:
class Message
{
public:
typedef std::string string;
// ctor
Message(string);
// dtor
~Message();
// copy ctor
Message(const Message&);
// assignment operator
Message& operator=(const Message&);
// getters
uint8 getLength() const;
const string& getData() const;
const uint8* getCSTR() const;
// setters
void setData(const string&);
protected:
// ctor
Message() : m_contents("") { }
// contents of entire message
string m_contents;
};
So I guess it all boils down to this:
What is the best way to define a constant array of characters/hex values (each message cargo) for a class, (and still be able to pass it in the initialization list of the constructor)? Or, tell me the obvious way to do this that I am missing.
Note: For other message classes, the cargo will be dynamic content, but always fixed length.
Note2: I will eventually have a director class which will own a CustomMessageBuilder() and tell it to buildMessage().
Any help, advice, criticism etc would be much appreciated.
Static const members can be initialized outside of the class.
#include <iostream>
class A
{
public:
static const char cargo[4];
};
const char A::cargo[4] = {0x65, 0xc7, 0xb4, 0x45};
int main()
{
std::cout << A::cargo[0] << A::cargo[1] << A::cargo[2] << A::cargo[3] << std::endl;
}