Defining const static that needs setting up at runtime - c++

I'm making use of a class with a few utilities defined as static methods eg.
QDate SSIMUtils::ConvertSSIMDate(QString s) {
QDate rtnDt;
//...conversion code
return rtnDt;
}
I would like to define a few constants in this class eg. LOW_DATE and was thinking of putting in something like
const static QDate LOW_DATE; // Need to set this somewhere to 1/1/1970
Unfortunately, I can't define it pre-compile time like I would say an int eg.
const static int SSIMUtils::myI = 4;
because it requires the use of a setDate method.
My question is how should I define a static const that I need to set up codewise, as the constant requires initialisation. I'd been thinking of defining it in the .h file eg.
const static QDate LOW_DATE;
then in the .cpp file, at the top, doing something like
SSIMUtils::LOW_DATE.setDate(1970,1,1);
But this is syntactically incorrect. What I'd ultimately like to do is use this constant in other classes eg.
if (myQDate.compare(SSIMUtils::LOW_DATE)==0) {
// do something.
}
What's the right way to set up a constant value in a static class that you need to adjust at run time ie. like a constructor?

As I mentioned in a comment, QDate has a constructor equivalent to setDate(), which allows for initialisation of a 'const' object.
You must declare your static constant the following way:
myclass.h:
#include <QDate>
class myclass {
public:
const static QDate CONST_DATE;
};
myclass.cpp:
#include "myclass.h"
const QDate myclass::CONST_DATE(1970, 1, 1);
I tested this using a std::string instead of a QDate (no QT available right now), and it works just as you want.

It depends on where the necessary information for the
initialization comes, or rather, when it is available. If it's
always available, and the type supports copy, then you can
just write a function which returns the initialized type:
namespace {
MyType getInitialized()
{
MyType results;
// ...
return results;
}
}
static MyType const lowDate( getInitialized() );
If it doesn't support copy, you can derive from it, providing
a specialized constructor:
class MyTypeInitialized : public MyType
{
public:
MyTypeInitialized()
{
// ...
}
};
MyTypeInitialized lowDate;
This has the disadvantage of masking the true type from the
client code, but otherwise works well.
If the information isn't available until later; e.g. it depends
on command line arguments, then you may have to use a variant of
the singleton idiom, where you have two instance functions:
one of which takes the necessary arguments for initialization,
and must be called first. (Or that may even be overkill; it
might be sufficient to have a global std::unique_ptr<MyType
const> lowDate;, and initialize that with an object newed at
the start of main. The main different is in the client
syntax.)

You cannot change something declared constant at run-time, by definition.
The closest you can get to run-time constant initialization is to initialize in a class'
constructor initializer list:
SomeClass(int constantValue) :
myConstant(constantValue)
{
...
}
Given that you are building a static class, you are probably not constructing an object though. You can always resort to having a setter method which only allows setting the value once (in which case you can not declare the field const, obviously).

As the name implies, it is a constant, it cannot (should not) be changed once initialised. The only place that you can assign a value to a constant member variable is in the constructor (that is, without weird const_casts).

Your QDate may be trivial to construct -- using a static constant may not be better than creating a new date for that constant each time the function is called.
In the interest of answering the question, let's assume it is complex to construct and that a static constant is best idea. You can simply write:
QDate SSIMUtils::ConvertSSIMDate(QString s) {
static const QDate LOW_DATE( /* ...construct it... */ );
QDate rtnDt;
//...conversion code
return rtnDt;
}
Note: Looks like SirDarius explained how you can construct this type directly, without an intermediate (+1), although a function-local static constant is generally much better than a global constant because global constants lead to some very tough initialization problems in C++.
This creates a function local static which will be initialized once, and in a thread safe manner before it is read and when the function is called.
If the instance cannot be constructed easily, it helps at times to initialize using the copy constructor and then creating an accessory function:
QDate SSIMUtils::ConvertSSIMDate(QString s) {
struct F { static QDate Low() { return ...; } };
static const QDate LOW_DATE(F::Low()); // << initialize the constant using the copy ctor
QDate rtnDt;
//...conversion code
return rtnDt;
}
So the short approach using the construction provided by SirDarius using a function-local-static is:
QDate SSIMUtils::ConvertSSIMDate(QString s) {
static const QDate LOW_DATE(1970, 1, 1);
QDate rtnDt;
//...conversion code
return rtnDt;
}

Related

C++ equivalent of Java static final String

I often need to define string constants associated with a class. Examples would be XML attributes, default filenames and many more.
In Java I would simply define something like
public static final String KEY = "attribute";
inside the class or interface.
In C++ the following would not compile:
class Example {
public:
static const std::string KEY = "attribute";
}
Instead, I would have to write:
class Example {
public:
static const std::string KEY;
}
const std::string Example::KEY = "attribute";
This is something I absolutely want to avoid because of its redundancy and verbosity.
The best solution I found so far is to use functions:
class Example {
public:
static std::string KEY() const { return "attribute"; }
}
This also provides some encapsulation and flexibility. However it might seem a bit weird to use a function just to define a constant.
So my question is, does this solution have major drawbacks and if yes, what are better alternatives?
In c++03, your best option is to use a function the way you are using, and this is awkward. The only thing is, why are you returning std::string and paying it's construction price, when you can return const char* const free of charge.
If, for some reason, you really have to have const std::string (again, it runs against my whole experience, so you might want to reconsider) following code works best in terms of efficiency (your current version calls std::string constructor on every call!):
class Example {
public:
static const std::string& key() {
static const std::string the_key = "That's my key!";
return the_key;
}
}
In c++11, you have several options, of which I find the best a constexpr:
class Example {
public:
static constexpr const char* const KEY = "TheKey";
}
The other option is in-place initialization of your const string, but why pay the price of it?
class Example {
public:
static const std::string KEY = "TheKey";
};
Whereas with Java, classes and their static members are loaded along with the class—which means that the class as a unit, or as part of a JAR, is replaceable—in C++ it doesn't go that way. If you stick things in headers, you pay the price of not being able to replace them until you re-compile everything that included them.
That's why the idiomatic—and most beneficial—way would be to indeed declare them in the header and provide the implementation where it belongs, in the translation units, which can be linked in to whatever other binaries. So consider readjusting your outlook (I moved from C# to C++ so I had this happen to me more than once).
But you don't have to go the way of strings at all. You can create enums, which is a much more elegant and type safe way to achieve this sometimes. With enums (and specifically enum classes), you can't just pass in the wrong string. You have to pass in one of a set of valid values.
As an example you could do:
class Example {
public:
enum class Attributes {
One,
Two,
// ...
};
}
And then, when it matters, and when you have local knowledge of what's what, you can map the enum values to actual strings or whatnot that the actual implementation requires.
You can define constructor of the class so that each time the class is used the constructor will automatically assign the value "attribute to the string"
class Example {
public:
static const std::string KEY;
Example()
{
KEY="Attribute";
}
};

consts inside classes?

Hi I was trying to define a constant inside a class, doing it the normal or usual way doesnt seem to work
class cat
{
public:
cat();
~cat();
private:
static const int MAX_VALUE = -99999;
int Number;
public:
void OrganizeNumbers();
void SetNumbers();
};
So the solution I found after doing some research was to declare it as static but what does this means and also I want to ask it is really necesary to declare a constant, becuase as you can see it is private right? i means it can only be accessed by the class methods so why to set a constant and also I read that using static only allows you to use integral type so its actually a dissavantage... if you are thinking to make a game.
static means that the member will be shared across all instances of your object.
If you'd like to be able to have different values of a const member in different instances you'll need to use a initialization list to set it's value inside your constructor.
See the following example:
#include <string>
struct Person {
Person (std::string const& n)
: name (n)
{
// doing: 'name = n' here is invalid
}
std::string const name;
};
int main (int argc, char *argv[]) {
Person a ("Santa Claus");
Person b ("Bunny the Rabbit");
}
Further reading
[10] Constructors - parashift.com/cpp-faq
10.1 Construct Initialization List
Initialization Lists in C++
1) Declare it "private" if you're only going to use MAX_VALUE inside your class's implementation, declare it under "public" if it's part of your class's interface.
2) Back in "C" days, "static" was used to "hide" a variable from external modules.
There's no longer any need to do this under C++.
The only reason to use "static" in C++ is to make the member class-wide (instead of per-object instance). That's not the case here - you don't need "static".
3) The "const" should be sufficient for you.
4) An (older-fashioned) alternative is to define a C++ enum (instead of a "const int")
There seems to be some confusion of ideas here:
A static member doesn't have to be an integral type, the disadvantage you mention does not exist.
const and private are unrelated, just because a member can only be accessed from instances of a given class, doesn't mean that nothing is going to change it.
Being const-correct guards against runtime errors that may be caused by a value changing unexpectedly.
you have to init the const attribute in the constructor with :
cat() : MAX_VALUE(-99999) {}
(which was declare as const int MAX_VALUE;)

Is it ok to call a function in constructor initializer list?

My gut feeling is it is not. I am in the following situation:
class PluginLoader
{
public:
Builder* const p_Builder;
Logger* const p_Logger;
//Others
};
PluginLoader::PluginLoader(Builder* const pBuilder)
:p_Builder(pBuilder), p_Logger(pBuilder->GetLogger())
{
//Stuff
}
Or should I change the constructor and pass a Logger* const from where PluginLoader is constructed?
That's perfectly fine and normal. p_Builder was initialized before it.
What you have is fine. However, I just want to warn you to be careful not to do this: (GMan alluded to this, I just wanted to make it perfectly clear)
class PluginLoader
{
public:
Logger* const p_Logger; // p_Logger is listed first before p_Builder
Builder* const p_Builder;
//Others
};
PluginLoader::PluginLoader(Builder* const pBuilder)
:p_Builder(pBuilder),
p_Logger(p_Builder->GetLogger()) // Though listed 2nd, it is called first.
// This wouldn't be a problem if pBuilder
// was used instead of p_Builder
{
//Stuff
}
Note that I made 2 changes to your code. First, in the class definition, I declared p_Logger before p_Builder. Second, I used the member p_Builder to initialize p_Logger, instead of the parameter.
Either one of these changes would be fine, but together they introduce a bug, because p_Logger is initialized first, and you use the uninitialized p_Builder to initialize it.
Just always remember that the members are initialized in the order they appear in the class definition. And the order you put them in your initialization list is irrelevant.
Perfectly good practice.
I would suggest this (but its on a purely personal level):
instead of having functions called in your constructor, to group them in a init function, only for flexibility purposes: if you later have to create other constructors.

Static constant string (class member)

I'd like to have a private static constant for a class (in this case a shape-factory).
I'd like to have something of the sort.
class A {
private:
static const string RECTANGLE = "rectangle";
}
Unfortunately I get all sorts of error from the C++ (g++) compiler, such as:
ISO C++ forbids initialization of
member ‘RECTANGLE’
invalid in-class initialization of static data member of non-integral type ‘std::string’
error: making ‘RECTANGLE’ static
This tells me that this sort of member design is not compliant with the standard. How do you have a private literal constant (or perhaps public) without having to use a #define directive (I want to avoid the uglyness of data globality!)
Any help is appreciated.
You have to define your static member outside the class definition and provide the initializer there.
First
// In a header file (if it is in a header file in your case)
class A {
private:
static const string RECTANGLE;
};
and then
// In one of the implementation files
const string A::RECTANGLE = "rectangle";
The syntax you were originally trying to use (initializer inside class definition) is only allowed with integral and enum types.
Starting from C++17 you have another option, which is quite similar to your original declaration: inline variables
// In a header file (if it is in a header file in your case)
class A {
private:
inline static const string RECTANGLE = "rectangle";
};
No additional definition is needed.
In C++11 you can do now:
class A {
private:
static constexpr const char* STRING = "some useful string constant";
};
Inside class definitions you can only declare static members. They have to be defined outside of the class. For compile-time integral constants the standard makes the exception that you can "initialize" members. It's still not a definition, though. Taking the address would not work without definition, for example.
I'd like to mention that I don't see the benefit of using std::string over const char[] for constants. std::string is nice and all but it requires dynamic initialization. So, if you write something like
const std::string foo = "hello";
at namespace scope the constructor of foo will be run right before execution of main starts and this constructor will create a copy of the constant "hello" in the heap memory. Unless you really need RECTANGLE to be a std::string you could just as well write
// class definition with incomplete static member could be in a header file
class A {
static const char RECTANGLE[];
};
// this needs to be placed in a single translation unit only
const char A::RECTANGLE[] = "rectangle";
There! No heap allocation, no copying, no dynamic initialization.
Cheers, s.
In C++ 17 you can use inline variables:
class A {
private:
static inline const std::string my_string = "some useful string constant";
};
Note that this is different from abyss.7's answer: This one defines an actual std::string object, not a const char*
This is just extra information, but if you really want the string in a header file, try something like:
class foo
{
public:
static const std::string& RECTANGLE(void)
{
static const std::string str = "rectangle";
return str;
}
};
Though I doubt that's recommended.
The class static variables can be declared in the header but must be defined in a .cpp file. This is because there can be only one instance of a static variable and the compiler can't decide in which generated object file to put it so you have to make the decision, instead.
To keep the definition of a static value with the declaration in C++11
a nested static structure can be used. In this case the static member
is a structure and has to be defined in a .cpp file, but the values
are in the header.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
Instead of initializing individual members the whole static structure is initialized in .cpp:
A::_Shapes A::shape;
The values are accessed with
A::shape.RECTANGLE;
or -- since the members are private and are meant to be used only from A -- with
shape.RECTANGLE;
Note that this solution still suffers from the problem of the order of
initialization of the static variables. When a static value is used to
initialize another static variable, the first may not be initialized,
yet.
// file.h
class File {
public:
static struct _Extensions {
const std::string h{ ".h" };
const std::string hpp{ ".hpp" };
const std::string c{ ".c" };
const std::string cpp{ ".cpp" };
} extension;
};
// file.cpp
File::_Extensions File::extension;
// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };
In this case the static variable headers will contain either { "" }
or { ".h", ".hpp" }, depending on the order of initialization created by the linker.
As mentioned by #abyss.7 you could also use constexpr if the value of the variable can be computed at compile time. But if you declare your strings with static constexpr const char* and your program uses std::string otherwise there will be an overhead because a new std::string object will be created every time you use such a constant:
class A {
public:
static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
foo(A::STRING); // a new std::string is constructed and destroyed.
}
To use that in-class initialization
syntax, the constant must be a static
const of integral or enumeration type
initialized by a constant expression.
This is the restriction. Hence, in this case you need to define variable outside the class. refer answwer from #AndreyT
possible just do:
static const std::string RECTANGLE() const {
return "rectangle";
}
or
#define RECTANGLE "rectangle"
You can either go for the const char* solution mentioned above, but then if you need string all the time, you're going to have a lot of overhead.
On the other hand, static string needs dynamic initialization, thus if you want to use its value during another global/static variable's initialization, you might hit the problem of initialization order. To avoid that, the cheapest thing is accessing the static string object through a getter, which checks if your object is initialized or not.
//in a header
class A{
static string s;
public:
static string getS();
};
//in implementation
string A::s;
namespace{
bool init_A_s(){
A::s = string("foo");
return true;
}
bool A_s_initialized = init_A_s();
}
string A::getS(){
if (!A_s_initialized)
A_s_initialized = init_A_s();
return s;
}
Remember to only use A::getS(). Because any threading can only started by main(), and A_s_initialized is initialized before main(), you don't need locks even in a multithreaded environment. A_s_initialized is 0 by default (before the dynamic initialization), so if you use getS() before s is initialized, you call the init function safely.
Btw, in the answer above: "static const std::string RECTANGLE() const" , static functions cannot be const because they cannot change the state if any object anyway (there is no this pointer).
The current standard only allows such initialization for static constant integral types. So you need to do as AndreyT explained. However, that will be available in the next standard through the new member initialization syntax.
Fast forward to 2018 and C++17.
do not use std::string, use std::string_view literals
please do notice the 'constexpr' bellow. This is also an "compile time" mechanism.
no inline does not mean repetition
no cpp files are not necessary for this
static_assert 'works' at compile time only
using namespace std::literals;
namespace STANDARD {
constexpr
inline
auto
compiletime_static_string_view_constant() {
// make and return string view literal
// will stay the same for the whole application lifetime
// will exhibit standard and expected interface
// will be usable at both
// runtime and compile time
// by value semantics implemented for you
auto when_needed_ = "compile time"sv;
return when_needed_ ;
}
};
Above is a proper and legal standard C++ citizen. It can get readily involved in any and all std:: algorithms, containers, utilities and a such. For example:
// test the resilience
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
return STANDARD::compiletime_static_string_view_constant();
};
return return_by_val();
};
return return_by_val();
};
return return_by_val();
};
// actually a run time
_ASSERTE(return_by_val() == "compile time");
// compile time
static_assert(
STANDARD::compiletime_static_string_view_constant()
== "compile time"
);
Enjoy the standard C++

C++ equivalent for java final member data

First, my latest coding is Java, and I do not want to "write Java in C++".
Here's the deal, I have to create an immutable class. It's fairly simple. The only issue is that getting the initial values is some work. So I cannot simply call initializes to initialize my members.
So what's the best way of creating such a class? And how can I expose my immutable / final properties to the outside world in C++ standards?
here's a sample class:
class Msg {
private:
int _rec_num;
int _seq;
string text;
public:
Msg(const char* buffer) {
// parse the buffer and get our member here...
// ... lots of code
}
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
};
C++ offers some nice mechanisms to make your class immutable. What you must do is:
declare all your public (and maybe protected) methods const
declare (but not define) operator= as private
This will ensure that your objects cannot be modified after they have been created. Now, you can provide access to your now immutable data members anyway you want, using const methods. Your example looks right, provided that you make it const:
int get_rec_num() const { return _rec_num; }
EDIT: Since C++11 you can explicitly delete operator=, rather than just leave it undefined. This explicitly instructs the compiler to not define a default copy assignment operator:
Msg& operator=(const Msg&) = delete;
I'd mark your immutable member as 'const', and assign it a value in your constructor initializer list.
I'd also parse your buffer outside of the class, and pass in the string to the constructor.
Something like this:
class Msg {
private:
int _rec_num;
int _seq;
const std::string text;
public:
Msg(const std::string& str) :
text(str)
{
}
// does this look like proper C++?
int get_rec_num() const { return _rec_num; }
};
// parse the buffer and get our parameter somewhere else
NB:
You should make any member functions that do not change the state of your class internals as 'const'; as this will allow you to call them with const objects.
You should avoid inluding a using std::string in header files; as anyone who includes your header has this 'using' forced upon them.
You're on the right track -- use getters for everything, and without any setters, your class is effectively immutable.
Don't forget some of the corner cases though -- you might want to declare the operator=() method as private and not implement it so someone can't override the object with the default compiler generated assignment operator, etc.
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
You should use
int get_rec_num() const { return _rec_num; }
(see the const which allows to call the member on const objects).
To make a variable immutable you have to use the const key word eg const int _rec_num. Const variables can only be initialised through an initialisation list, which gets called before any code in the constructor. This means that you cannot do any processing in the constructor which sets the const member variables.
You have two ways round this, first you can create another internal class which takes in a buffer and parses it into your variables. Put a const version of this into your MSG class and put this in the initialisation list:
class MsgInner
{
public:
int _rec_num;
Msg(const char* buffer) {
// Your parsing code
}
};
class Msg
{
public:
const MsgInner msg;
Msg(const char* buffer) : msg(buffer)
{ // any other code }
};
This is perhaps not so 'standard', but it's another perspective. Otherwise you can also do it as the other answers have suggested with get methods.
On Finalizers
There is none, you have to emulate it. Either by using a cleanup function or by having all your resources encapsulted in RAII classes. The compiler will place static machinery in your application to call destructors on your RAII classes --i.e., when they go out of scope the resources get released through the destructor.
On Immutability and Initialization
Generally if something is immutable and const-correct the class will have all of its members as const and the only time you get to "write" to them is when the class is initialized. However in your case that might not be possible.
I suggest you gather all your resources and initialize the class (via a non-default constructor with const members) once you have them. The other alternative (which I do not abide) is to have a mutator function that "claims" to be const correct but writes to the const values for a one-time post construction initialization.
First of all, it is possible to initialize the members efficiently and at construction time even if they were declared as const (which is neither necessary nor recommended).
I would still suggest that you split this class into two separate classes (pseudo-code):
// Msg: pure data object; copy constructible but not modifiable.
class Msg
{
public:
Msg(int rec_num, ...)
: rec_num_(rec_num)
...
{}
int rec_num() const
{ return rec_num_; }
...
private:
// prevent copying
Msg& operator=(Msg const&);
private:
int rec_num_;
};
// MsgParser: responsible for parsing the buffer and
// manufacturing Msg's.
class MsgParser
{
public:
static Msg Parse(char const* buffer)
{
... parse ...
return Msg(...);
}
};
// Usage
Msg const msg = MsgParser::Parse(buffer);
This also nicely separates the concerns of holding and parsing the data into separate classes.