C++ large string initialization and use - c++

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"};
};

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.

C++ pointer to class method

I want to do something like this:
struct CLI_Command{
CLI_Command(char* s, void (*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (*handler)(void);
};
class CLI {
public:
CLI();
private:
CLI_Command cli_table[NO_CLI_COMMANDS] = {
CLI_Command("Command1", handler1),
CLI_Command("Command2", handler2)
};
void handler1(){};
void handler2(){};
};
I know that I need something similar to CLI::*handler, but I can't get the syntax right. I keep running into errors like this:
"error: no matching function for call to 'CLI_Command::CLI_Command(const char [4], <unresolved overloaded function type>)"
This illustrates the correct syntax:
class CLI;
struct CLI_Command
{
CLI_Command(char* s, void (CLI::*h)(void))
{
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
void raise( CLI* the_cli ) { return (the_cli->*handler)(); }
};
class CLI
{
public:
CLI();
private:
static CLI_Command cli_table[NO_CLI_COMMANDS];
void handler1(){};
void handler2(){};
};
CLI::CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", &CLI::handler1 },
{ "Command2", &CLI::handler2 }
};
Names of member functions do not decay to pointer-to-member. You must use & explicitly, and a qualified name, when creating a pointer-to-member.
In addition to other answers, another option is to use std::function together with std::bind():
struct CLI_Command{
...
std::function<void> handler;
};
class CLI {
...
CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", std::bind(&CLI::handler1, this) },
{ "Command2", std::bind(&CLI::handler2, this) }
};
void handler1(){};
void handler2(){};
};
void handler1(){}
void handler2(){}
are member functions of CLI. The correct way to "address to" them is &CLI::handler1 and not handler1. However then, they won't be accepted by void (*h)(void), which would need to be changed to void (CLI::*h)(void). But that is probably not what you want.
Maybe consider reading about std::function for type erasure, or make your handler1/handler2 static.
You should use the syntax for a pointer to class member instead of the syntax for a loose function pointer.
class CLI;
struct CLI_Command{
CLI_Command(char* s, void (CLI::*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
};
In addition, make sure you call the function through the pointer of the current CLI class;
void CLI::process(char *cmd) {
CLI_Command command* = /* lookup the command */
this->(command->handle)();
}
To get it working, make your methods static
static void handler1(){};
static void handler2(){};
Whatever consequences (read here please, for more detailed info) this will have :-( .

Initialize static object graph

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?

What is the equivalent to a java static final member variable in C/C++ and how can you initialize it via some computation?

In java, you can have something like:
public class Foo {
public static final int myStatic = computeValue();
private int static computeValue() { ... }
}
Is there something analogous in C/C++? (note - I cannot use c++11 which sadly has all sorts of goodies)
I would like something like
/*static final*/ size_t charsInLong = snprintf(NULL, 0, "%l", MAX_LONG)
Not a java expert, but pretty sure
class Foo {
public:
static int myStatic;
private:
static int computeValue() { return 1; }
};
int Foo::myStatic(computeValue());
is equivalent to your Java code (which did not contain the 'final' keyword). To prevent modification of myStatic use const:
class Foo {
public:
const static int myStatic;
private:
static int computeValue() { return 1; }
};
const int Foo::myStatic(computeValue());
The closest analogy to java's final in C++ is const though they're not quite identical. A const var in C++ cannot be modified after it is initialized.
You could use a static method something like this:
class foo {
public:
static int bar()
{
static int barval = computation();
return barval;
}
};
N.B. This is NOT thread safe! Making it so is left as an exercise for the reader.

C++ -- how to initialize the static variable inside a member function?

void ClassA::Func()
{
static map<int, string> mapIntStr;
mapIntStr[0] = m_memberVariable0; <= just want to do once & m_memberVariable* are not static
mapIntStr[1] = m_memberVariable1; <= just want to do once
...
}
I want to ONLY initialize the variable mapIntStr once. As we know, we can put the initialize code inside a static function and call that static function and store the return value into mapIntStr.
Here I would like to get a quick & dirty solution. As I remember, there is something called static scope. I would like to initialize mapIntStr ONCE without calling a static function. how can I do it?
Thank you
void ClassA::Func()
{
static map<int, string> mapIntStr;
if(mapIntStr.empty()){
mapIntStr[0] = m_memberVariable0;
mapIntStr[1] = m_memberVariable1;
// ...
}
}
How about that? :)
Edit
Well, the best solution would be to take the mapIntStr out of the function and into the class. And then you won't get around the static function call.
//in ClassA.h
class ClassA{
public:
void Func();
static map<int,string> InitStatic();
static map<int,string> mapIntStr;
};
//in ClassA.cpp
#include "ClassA.h"
void ClassA::Func(){
// use mapIntStr
}
map<int,string> ClassA::InitStatic(){
map<int,string> ret;
// init ret
return ret;
}
map<int,string> ClassA::mapIntStr = ClassA::InitStatic();
That're about the only options that I know of. So you've got the choice. Initialize the map once in the func or even in a contructor the first time a ClassA object is created (better version of the two) and live with the overhead of a nearly noop call to empty(), which will most likely be a single instruction only after proper inlining and will impose no overhead whatsoever, or use a static initialization function.
Create a inside struct, then initialize everything in the constructor of that struct, and then you declare a static variable of that struct.
void fun()
{
struct setter
{
setter(){}
};
static setter setup;
}
For your case:
void ClassA::Func()
{
struct Map : public std::map<int, string>
{
Map()
{
(*this)[0] = something;
(*this)[1] = somethingElse;
}
}
static Map map;
}