static const member initialization from file - c++

How do you initialize a static const member with a value that is stored in a file? For example:
Class Foo
{
private:
static const String DataFromFile;
void InitData (void);
};
I know for a short value, I can initialize with:
const String DataFromFile = "Some Value";
But what if the value is really a "big" value and encrypted and stored in a disk file? I need to decrypt it before putting it into DataFromFile.
Is there a way to do it or can I just forget it and treat it as a regular variable? That is, instead of:
static const String DataFromFile;
can I just declare it as:
String DataFromFile;
and initialize it with a function?

How do you initialize a static const member with a value that is
stored in a file? For example:
Like this:
//X.h
#include <string>
class X
{
//...
static const std::string cFILE_TEXT_;
static const bool cINIT_ERROR_;
};
//X.cpp
//...#include etc...
#include <fstream>
#include <stdexcept>
namespace {
std::string getTextFromFile( const std::string& fileNamePath )
{
std::string fileContents;
std::ifstream myFile( fileNamePath.c_str() );
if( !(myFile >> fileContents) );
{
return std::string();
}
return fileContents;
}
}
const std::string X::cFILE_TEXT_( getTextFromFile( "MyPath/MyFile.txt" ) );
const bool X::cINIT_ERROR_( cFILE_TEXT_.empty() );
X::X()
{
if( cINIT_ERROR_ )
{
throw std::runtime_error( "xxx" );
}
}

Related

How to check conditions on a string literal at compile time passed inside a class?

I want to be able to pass a string literal to a class instance and also check at compile time for certain conditions on the string literal. But I want the string checking to be done by the class somehow. I have a sample code with roughly what I'm trying to achieve:
#include <type_traits>
#include <string>
#include <string_view>
class TestString
{
public:
constexpr bool TestStringCondition(const char* name) noexcept
{
return std::string_view(name).find('a') != std::string_view::npos; //random condition
}
constexpr TestString(const char* name) noexcept:
m_name(name)
{
static_assert(TestStringCondition(name), "error message");
}
const char* m_name = nullptr;
};
int main()
{
static constexpr const char* const name = {"foo"};
static const TestString testString { name };
}
I tried various options (templates, char_traits, etc.) but keep getting compiler error "static_assert expression is not an integral constant expression". It seems to not be happy with the stringliteral passed as a parameter as I can do the assert check outside the class. I cannot use any c++20 features yet and I want a way avoiding Boost. Does anyone know a way?
The following works but I am unsure if it is what you want:
#include <type_traits>
#include <string_view>
template<const char *const t_name>
class TestString {
public:
static constexpr bool TestStringCondition(const char *name) noexcept {
return std::string_view(name).find('a') != std::string_view::npos; // random condition
}
constexpr TestString() noexcept {
static_assert(TestStringCondition(t_name));
}
};
constexpr char okay[] = "okay"; // array, so it is a static object with linkage
int main() {
static const TestString<okay> testString{};
}

Why is my member variable dissapearing at the end of each loop iteration?

In the following loop, I am taking string variables from one vector and using them in the constructor for a bunch of elements that will be added to another constructor.
while (std::getline(qt_prim_file_stream, temp_str, '\n')) {
if (temp_str.empty()) // Blank line implies new module
{
//output_wires is a vector of string
std::string cur_output_wire=output_wires[m_hex_to_SOP.size()];
SOPExpr expr(current_SOP_string, cur_output_wire);
m_hex_to_SOP.push_back(expr);
current_SOP_string.clear();
i_3++;
continue;
}
current_SOP_string.append(temp_str);
current_SOP_string.push_back('\n');
i_2++;
}
My problem is that the second member string variable (m_output_wire) of SOPExpr in each SOPExpr in m_hex_to_SOP (a vector of SOPExpr) keeps dissapearing at the end of each loop (gets set to ""). Why is this happeing? The first member variable (m_gate_level_netlist) doesn't get set to "".
Here is the header for SOPExpr.h
#include <string>
#include <vector>
#include <ostream>
#include <iostream>
class SOPExpr {
std::string m_gate_level_netlist;
std::string m_output_wire;
public:
const std::string &getMOutputWire() const;
public:
SOPExpr(const std::string &m_gate_level_netlist);
SOPExpr(const SOPExpr &expr);
SOPExpr();
SOPExpr(const std::string &mGateLevelNetlist, const std::string &mOutputWire);
const std::string &getGateLevelNetList() const;
};
and here is the class file:
#include "SOPExpr.h"
SOPExpr::SOPExpr(const SOPExpr &expr) {
m_gate_level_netlist = expr.getGateLevelNetList();
}
SOPExpr::SOPExpr() {}
const std::string &SOPExpr::getGateLevelNetList() const {
return m_gate_level_netlist;
}
SOPExpr::SOPExpr(const std::string &mGateLevelNetlist,
const std::string &mOutputWire)
: m_gate_level_netlist(mGateLevelNetlist), m_output_wire(mOutputWire) {}
Presumably, m_hex_to_SOP is defined as std::vector, right?
In that case, when you call m_hex_to_SOP.push_back(expr); you are actually invoking this copy constructor:
SOPExpr::SOPExpr(const SOPExpr &expr) {
m_gate_level_netlist = expr.getGateLevelNetList();
}
which does not copy m_output_wire.

I want to pass in constructor mode of file

I created child class of ofstream. I want to pass in constructor mode of file. For example ios::app. How can i do it ? What should i write in my_file constructor to put it in ofstream class constructor? I know that it's int type but how to understand what is value of ios::app?
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
class my_file : public ofstream {
string name;
public:
my_file(string name, const char* filename) : ofstream(filename) { this->name = name; }
inline const string get() { return this->name; }
};
int main(void) {
my_file file("Name","new.txt" /* , ios::app */ );
return 0;
}
I know that it's int type but how to understand what is value of ios::app?
Wrong, that's not a int!
Go to ofstream doc http://www.cplusplus.com/reference/fstream/ofstream/, then click (constructor) to see what the parameters are and then you can see that mode is of type std::ios_base::openmode (as described here)
So simply do:
class my_file : public ofstream {
string name;
public:
my_file(string name, const char* filename, std::ios_base::openmode mode ) : ofstream(filename,mode) { this->name = name; }
inline const string get() { return this->name; }
};
Then:
my_file file("Name","new.txt", ios::app);

How to initialize a static variable with another static variable?

Static1.hpp
#include <string>
class Static1
{
public:
static const std::string my_string;
};
Static1.cpp
#include "Static1.hpp"
const std::string Static1::my_string = "aaa";
Static2.hpp
#include <string>
class Static2
{
public:
static const std::string my_string;
};
Static2.cpp
#include "Static2.hpp"
const std::string Static2::my_string = Static1::my_string;
main.cpp
#include "Static2.hpp"
#include <iostream>
int main(argc int, char** argv)
{
cout << to_string(Static2::my_string == "aaa") << endl;
return 0;
}
If I put add_executable(printMyString main.cpp Static2.cpp Static1.cpp) in my CMakeLists.txt, I get
0
while add_executable(printMyString main.cpp Static2.cpp Static1.cpp) gives me the expected behavior of
1
To make my code easier to maintain (so that I don't need to keep track of the order I list my source files), is there any way I can ensure that I get the behavior where Static2::my_string == "aaa"?
You are experiencing effects of a static initialization order fiasco.
The usual work-around is to substitute your static variables with functions that have a static variable in the scope, initialize, and return it.
Here is how it could be done for your example: Live Example (order1)
Live Example (order2)
class Static1
{
public:
static std::string my_string();
};
...
std::string Static1::my_string()
{
static const std::string my_string = "aaa";
return my_string;
}
...
class Static2
{
public:
static std::string my_string();
};
...
std::string Static2::my_string()
{
static const std::string my_string = Static1::my_string();
return my_string;
}
...
std::cout << std::to_string(Static2::my_string() == "aaa") << std::endl;

Include global variables in header file - c++

At the moment I am using a rather large piece of code to analyse data.
In this code apart from the analysis itself, I include some functions that will be used in the analysis, some function that are related to objects and some global variables. My code has the following structure
#include "header1.h"
#include "header2.h"
...
#define global_variable_1 1
#define global_variable_2 3
...
double function1(){
<code>
{
double function2(){
<code>
{
...
main(){
<code>
}
At the moment I want to make my code a bit more elegant, sophisticated and programmable correct. I am thinking of making a header file that will include the headers that I am using and some functions, a second header file with the rest of the functions and a last header file that will contain the global parameters that I use.
So I will have something like
#include "headers.h"
#include "functions.h"
#include "variables.h"
main(){
<code>
}
My question is whether it is programably proper to do so and if there is another and perhaps better way to include the global variables.
If you are trying to use variables that are global and you know that they are a constant value such as PI I would refrain from using both local globals and #define macros. This is a matter of preference but over time I've learned that it is better practice and more elegant to declare them as static const type name; in the header file and set the value accordingly in the cpp file. I also do not prefer to have a bunch of dangling values or basic methods hanging around so I usually will group similar types of values and methods and contain them in a class declaring them to be static. Here is an example:
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
#include <iostream>
#include <string>
#include <stdio.h>
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string& toUpper( std::string& str );
static std::string& toLower( std::string& str );
private:
Utility(); // Not Implemented - This class is not an object and can not be declared.
Utility( const Utility& c ); // Copy Constructor - Not Implemented
Utility& operator=( const Utility&c ); Assignment Operator - Not Implemented
}; // Utility
#endif // UTILITY_H
Utility.cpp
#include "Utility.h"
// -------------------------------------------------------------------------
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "Press any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// -------------------------------------------------------------------------
// toUpper()
std::string& Utility::toUper( std::string& str ) {
std::transform( str.begin(), str.end(), str.begin(), ::toupper );
return str;
} // toUpper
// -------------------------------------------------------------------------
// toLower()
std::string& Utility::toLower( std::string& str ) {
std::transform( str.begin(), str.end(), str.begin(), ::tolower );
return str;
} // toLower
To use these functions here is an example:
main.cpp
#include <iostream>
#include <string>
#include "Utility.h"
int main() {
std::string strHello( "Hello World!" );
std::cout << strHello << std::endl;
std::cout << Utility::toLower( strHello ) << std::endl;
std::cout << Utility::toUpper( strHello ) << std::endl;
Utility::pressAnyKeyToQuit();
return 0;
} // main
With this type of containment it is illegal to do this:
int main() {
Utility util;
util.pressAnyKeyToQuit();
} // main
This will fail because the Utility default constructor is private or inaccessible, however any type of function or variable that is declared as being static can be called through the scope resolution operator. Here is an example of const variables that would be considered globals.
GeneralMath.h
#ifndef GENERAL_MATH_H
#define GENERAL_MATH_H
class Math {
public:
static const float PI;
static const float PI_HAVLES;
static const float PI_2;
static const float ZERO;
inline static bool isZero( float fValue );
template<typename T>
inline static void swap( T& value1, T& value2 );
private:
Math();
Math( const Math& c ); // Not Implemented
Math& operator( const Math& c ); // Not Implemented
}; // Math
#include "GeneralMath.inl"
void dummy(); // does nothing used to have a method in the *.cpp file
#endif // GENERAL_MATH_H
GeneralMath.inl
// -------------------------------------------------------------------------
// isZero()
inline bool Math::isZero( float fValue ) {
if ( (fValue > -ZERO) && (fValue < ZERO) ) {
return true;
}
return false;
} // isZero
// -------------------------------------------------------------------------
// swap()
template<class T>
inline void Math::swap( T& value1, T& value2 ) {
T temp;
temp = value1;
value1 = value2;
value2 = temp;
} // swap
GeneralMath.cpp
#include "GeneralMath.h"
const float Math::PI = 4.0f * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_HALVES = 0.5f * Math::PI;
const float Math::PI_2 = 2.0f * Math::PI;
const float Math::ZERO = static_cast<float>( 1e-7 );
void dummy(){return;}
Using it in an example:
main.cpp
#include <iostream>
#include "Utility.h"
#include "GeneralMath.h"
int main() {
float value = 3.14957;
if ( Math::isZero( value - Math::PI ) ) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
Utility::pressAnyKeyToQuit();
return 0;
} // main
I prefer this approach so that when common stand alone methods and constant variables are frequently used in multiple files and have a similar grouping you do not have a bunch of #defines or global's declared everywhere.
Now on the other hand if a specific class object that you are creating depends on a specific constant value that is unique to it then you can have a global in its *.h or *.cpp file but again I would still declare it as a static const type name;
The simplicity of this is to include the *.h file where it is needed and use the class name with the scope resolution operator followed by the const variable or static method where it is needed.
You can also do a similar approach without using a class and not declaring them as static by containing them in a namespace, but this could cause problems because other developers might have the same name space and this could create conflicts to resolve names. This is why I prefer the class approach and declaring them as static members.
Remember these classes are not Objects and they can not be constructed and all members have to be static!