singleton class with static variable inside function(Meyer's implementation) - c++

Meyer's singleton class blueprint is declared in a header file temp.h. If temp.h is included in two seperate.cpp files then each one have its own blueprint and as static things are not visible to other modules(i.e *.o or *.cpp) hence each .cpp file should have its own object of temp class(means two instance of temp in the program). But i have checked it in the program, same instance is shared between both the .cpp files. I don't understand why?
//temp.h
class temp
{
public:
~temp() {}
void temp_func()
{
std::cout << "Inside temp_func" << "\n";
}
static temp& createInstance()
{
static temp ins;
return ins;
}
priave:
temp() {}
};
Another header file, without class instance(with builtin datatype)
//temp1.h
inline static int& createInstance()
{
static int ins;
return ins;
}
//another.cpp
#include "temp1.h"
void func()
{
int &t = createInstance();
std::cout << "t: " << t << "\n";
t = 20;
}
//main.cpp
#include "temp1.h"
void func();
int main()
{
int &temp = createInstance();
temp = 10;
std::cout << "temp:" << temp << "\n";
func();
std::cout << "temp:" << temp << "\n";
return 0;
}
Output of program
temp:10
t: 0
temp:10

Check this inline keyword explanation. Quoting:
There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables (since C++17)) all definitions are identical. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is #include'd in multiple source files.
Your createInstance function is exactly that kind of function - since you've defined it within class definition, it's implicitly inline. Thus compiler will merge them all together as if they were only one. As a result your function will return the same ins object.
Note, that function must be inline, otherwise something else happens - you violate one definition rule, to be precise:
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
EDIT:
in second case it's not about built-in type data, but about you moving createInstance function outside class. What it does? It changes meaning of static keyword you've added to function definition - now the function will be copied (instead of being shared or merged together, when linked), thus every translation unit gets its own copy of int ins variable. Remove static keyword:
//temp1.h
inline int& createInstance()
{
static int ins;
return ins;
}
and it works just fine:
temp:10
t: 10
temp:20

Yes, this is what is going to happen. Block-scoped static variables (often called function-level static), such as your static temp ins; inside createInstance behave very similar to global variables - i.e. they are shared across all translation units and are preserved until program terminates (there is a difference when it comes to beginning of their lifetimes, but we won't go there for now).
As a matter of fact, usually the underlying mechanism for generating code with regards to such static variables is extremely similar to the one used with usual global variables. You can even think of them as a global variable with a name prefixed with the name of the function (although it won't be exactly correct, it might steer your thought process in the right direction).
In this particular case, you have a static variable inside a (inline) function, and any translation unit which calls this function will end up sharing the same static variable.

Related

error: non-const static data member must be initialized out of line

class Solution {
public:
static int m=INT_MIN; // it shows error: non-const static data member must
be initialized out of line.(why?)
using "int m=INT_MIN" is fine.
int func(TreeNode*root){
if(root==NULL){
return 0;
}
int l=max(func(root->left),0);
int r=max(func(root->right),0);
m=max(l+r+root->val,m);
return max(l,r)+root->val;
}
int maxPathSum(TreeNode* root) {
if(root==NULL)
{
return 0;
}
m=INT_MIN;
int x=func(root);
return m;
}
};
I need to update the value of variable m. Therefore I am using static int data type. But the following error is coming.
Using int instead of static int is working fine. But why is static int giving error?
Bjarne Stroustrup explains this here:
A class is typically declared in a header file and a header file is
typically included into many translation units. However, to avoid
complicated linker rules, C++ requires that every object has a unique
definition. That rule would be broken if C++ allowed in-class
definition of entities that needed to be stored in memory as objects.
As said by Stroustrup, every class needs a unique definition. Now, as we know static members are associated directly with their class. Now consider the two cases:
The static member is also constant, then its initialization is allowed inline because the compiler can make its own optimisations and treat this member as a compile-time constant because it is guaranteed that its value will never change. So, as the value of this member is fixed, the definition of the class with which this member is associated is also fixed. So, the initialization is allowed inline.
The static member is not constant. Then its value can change later on during the execution of the program. So, the compiler can not make compile-time optimisations on this member. Hence, to prevent the complications that may arise while trying to initialize such a member when the class is loaded, inline initialisation of such members is not allowed.
PS: When I heard about this concept the very first time, I was also confused because it is not in accordance with the principle of orthogonality that is a feature desired by programmers. The principle of orthogonality will state that since we can combine int and static; and int and const, we should be able to write static const int and static int in a similar fashion. But this case here is an example of a situation where the developer of a language has to give up orthogonality for the users of the language in exchange of the simplicity of the compilation process.
Have a look at the concept of orthogonality here
To answer OPs question why
class Solution {
public:
int m = INT_MIN;
};
is fine but
class Solution {
public:
static int m = INT_MIN;
};
is not:
In short: Prefixing a data-member with static fundamentally change its meaning.
Without static, the member variable is part of the class and each instance will provide a separate storage for this member variable.
With static, the member variable has only scope of the class but there will be only one global storage.
Respectively, the initialization has different meanings too.
For non-static member variables, it provides a default initialization which constructors may use (or override).
Demonstration by Example:
#include <iostream>
enum ArgCase1 { Case1 };
enum ArgCase2 { Case2 };
class Solution {
public:
int m = 123;
Solution() = default; // will use m(123) implicitly
Solution(ArgCase1) { } // will use m(123) implicitly
Solution(ArgCase2): m(456) { } // default of m ignored
};
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Solution sol);
std::cout << "sol.m: " << sol.m << '\n';
DEBUG(Solution sol1(Case1));
std::cout << "sol1.m: " << sol1.m << '\n';
DEBUG(Solution sol2(Case2));
std::cout << "sol2.m: " << sol2.m << '\n';
}
Output:
Solution sol;
sol.m: 123
Solution sol1(Case1);
sol1.m: 123
Solution sol2(Case2);
sol2.m: 456
Live Demo on coliru
For static member variables, the initialization would be dangerous. Assuming that a class is declared in a header which is included multiple times, this would result in a violation of the One Definition Rule.
In former times, it was usual to declare the static member variable in the header but to define it in the .cpp-file (which represents the translation unit).
Expample:
solution.h:
#ifndef SOLUTION_H
#define SOLUTION_H
class Solution {
public:
static int m;
};
#endif // SOLUTION_H
solution.cc:
// header of this module:
#include "solution.h"
int Solution::m = 123;
Live Demo on coliru
Since C++17, a new alternative is available – using the keyword inline.
From cppreference.com – static members – Static data members
A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify an initializer. It does not need an out-of-class definition
Example:
solution.h:
#ifndef SOLUTION_H
#define SOLUTION_H
class Solution {
public:
inline static int m = 123;
};
#endif // SOLUTION_H
Live Demo on coliru
The advantage is that there is no .cpp-file needed for this i.e. as it is the class Solution could be provided as header-only source.

c++ Is 'static int' not working across multiple files?

for showing you, I made a very minimalist example of my problem about 1 header and 2 .cpp files. All I do is calling myfunc() and this shall get a value by cin>>. And then main shall print the value (+3). I get the error "a is not defined" for the main.cpp.
I thought static is somehow helping here, but it's not. I don't understand what the problem is.
(I am aware, that I could write cout << myfunc()+3; but it's for a general purpose).
header.h:
#ifndef header_h
#define header_h
int myfunc();
#endif
main.cpp:
#include <iostream>
#include "header.h"
int main()
{
myfunc();
std::cout << a + 3 << std::endl;
}
second.cpp:
#include"header.h"
int myfunc()
{
static int a;
std::cin >> a;
return a;
}
Your a variable is declared inside the function (so it is local to the scope) and hence cannot be accessed outside of it.
If you want access from main, declare it outside the scope of the function (a global variable).
int f() {
int x = 23 ;
return x ;
}
int main() {
std::cout << f() << std::endl ;
std::cout << x ; // Error! x is local to f() and there is no x declared globally or inside main()'s scope.
}
You could do something like this :
int a = myfunc();
std::cout << a ; // Now possible!
Edit: static variable declaration has nothing to do with scoping rules or accessibility. Declaring static merely implies a change in the life-time policy of the variable i.e. its life-time is throughout the program execution duration instead of the duration in which the instructions in the scope (in which the variable is declared) are executed. Thus declaring static does not imply that a variable can be accessed outside of its scope.
"static" does two things: It creates a variable that exists once through the life time of the program, and it makes sure that the variable is accessible by name only in the one compilation unit where it is defined (so if another compilation unit by chance declares something static with the same name, there is no clash).
That means that by design you cannot access a static variable declared in second.cpp from main.cpp. That's absolutely intentional.
In addition, your variable a is declared inside a function. That means it can be only accessed inside that function. So not even code in other functions in second.cpp can access it by name. Again, fully intentional.
Apart from that, if you got around these problems (and you can), storing the result of a function in a global variable and accessing it through that variable is usually considered a very bad programming practice.

non-deferred static member initialization for templates in gcc?

Does gcc have any guarantees about static member initialization timing, especially regarding template classes?
I want to know if I can get a hard guarantee that static members (PWrap_T<T>::p_s) will be initialized before main(), when classes are instantiated across multiple compilation units. It isn't practical to try to manually touch a symbol from each compilation unit at the start of main, but it isn't clear to me that anything else would work.
I've tested with methods like bar() in different units and always gotten the desired result, but I need to know when/if ever gcc will yank the rug out and whether it's preventable.
Furthermore, will all static members from a DSO be initialized before a library finishes loading?
#include <iostream>
#include <deque>
struct P;
inline std::deque<P *> &ps() { static std::deque<P *> d; return d; }
void dump();
struct P {
P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
void doStuff() { std::cout << id_ << " (" << inf_ << ")" << std::endl; }
int const id_;
char const *const inf_;
};
template <class T>
struct PWrap_T { static P p_s; };
// *** Can I guarantee this is done before main()? ***
template <class T>
P PWrap_T<T>::p_s(T::id(), T::desc());
#define PP(ID, DESC, NAME) /* semicolon must follow! */ \
struct ppdef_##NAME { \
constexpr static int id() { return ID; } \
constexpr static char const *desc() { return DESC; } \
}; \
PWrap_T<ppdef_##NAME> const NAME
// In a compilation unit apart from the template/macro header.
void dump() {
std::cout << "[";
for (P *pp : ps()) { std::cout << " " << pp->id_ << ":" << pp->inf_; }
std::cout << " ]" << std::endl;
}
// In some compilation unit.
void bar(int cnt) {
for (int i = 0; i < cnt; ++i) {
PP(2, "description", pp);
pp.p_s.doStuff();
}
}
int main() {
dump();
PP(3, "another", pp2);
bar(5);
pp2.p_s.doStuff();
}
(C++11 §3.6.2/4 - [basic.start.init]:)
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.
... A non-local variable with static storage duration having initialization with side-effects must be initialized even if it is not odr-used (3.2, 3.7.1).
Also, trying __attribute__ ((init_priority(int))) or __attribute__ ((constructor)) for the template member's initialization yielded warning: attributes after parenthesized initializer ignored, and I know no other tricks regarding static initialization.
Thanks in advance to anyone who can give me an answer about this!
The standard guarantees that static storage duration objects are initialized before any functions/variables in the same translation unit as your object are used from an external source.
The wording here is designed to work with shared libraries. Because shared libraries can be dynamically loaded after main() has started the language specification has to be flexible enough to cope with it. But as long as you access your object from outside the translation unit then you are guaranteed that it will have been constructed before you are given accesses (unless you are doing something pathological).
BUT this does not stop it being used before initialization if it is used in the constructor of another static storage duration object in the same compilation unit.
But you can easily manually provide guarantees that a static object is correctly initialized before used by using the technique below.
Just change the static variable to a static function. Then inside the function declare a static member that is returned. So you can use it exactly the same way as before (just add ()).
template <class T>
struct PWrap_T
{
static P& p_s(); // change static variable to static member function.
// Rather than the type being P make it a reference to P
// because the object will be held internally to the function
};
template <class T>
P& PWrap_T<T>::p_s()
{
// Notice the member is static.
// This means it will live longer than the function.
// Also it will be initialized on first use.
// and destructed when other static storage duration objects are destroyed.
static P p_s_item(T::id(), T::desc());
return p_s_item;
// Note its not guaranteed to be created before main().
// But it is guaranteed to be created before first use.
}
So here you get the benefits of a global (whatever they are). You get guaranteed construction/destruction and you know the object will be correctly constructed before it can be used.
The only change you need to make is:
void bar(int cnt) {
for (int i = 0; i < cnt; ++i) {
PP(2, "description", pp);
pp.p_s().doStuff();
// ^^ Add the braces here.
}
}
As you've already found out the C++ standard doesn't guarantee that "the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main". However, GCC does peform such initialization before executing main as described in How Initialization Functions Are Handled.
The only problem is initialization of static objects from shared libraries loaded with dlopen. These will only be initialized at the time the library is loaded, but there's nothing you can do about it.

Query on Static member variables of a class in C++

Sorry if this question seems trivial to many here.
In a C++ code there is something as below:
class Foo
{
public:
static int bands;
...
...
private:
...
...
}//class definition ends
int Foo::bands; //Note: here its not initialized to any value!
Why is the above statement needed again when 'bands' is once declared inside the class as static?
Also can a static variable be declared as a private member variable in any class?
C++ notes a distinction between declaring and defining. bands is declared within the class, but not defined.
A non-static data member would be defined when you define an object of that type, but since a static member is not a part of any one specific object, it needs it's own definition.
a) It's needed because that's the way the languge is designed.
b) Static variables are initialized by their default constructor, or to zero for built-in types.
c) Yes, they can be (and usually are) private.
Take a look at this question.
It has to do with obj files, how they are used, and how memory addresses for globally scoped variables are ultimately discovered through the linking process. Object files contain the addresses of all global data and functions defined in the corresponding cpp. They layout some memory in a relative fashion to tell the liker where in that file these global vars/funcs can be found. So for example
function doFoo can be found 0 bytes from beginning of this file
int foo::bands can be found 12 bytes from beginning of this file
etc
Its almost easier to think about if you've done straight C before. In a pure C world you would do things in a more traditional modular programming sense. Your module would be defined with a header and a cpp. The header would define a "public" variable like below, using the extern keyword, then instantiate it in the cpp.
foo.h
extern int bands;
foo.cpp
#include "foo.h"
int bands;
foo.obj:
int bands can be found 0 bytes from the beginning of this file
The "extern" keyword states that this name is valid and its address will get resolved at link time. Everyone that included "foo.h" and wanted to use the "bands" global variable had could now use it. At link time, the linker would figure out that bands existed in the foo.obj. If you forgot to put "int bands" in foo.obj, you'd get a linker error, and have to go resolve it.
In C++ using static in a class declaration i similar. You are telling the users that there exists this thing called "foo::bands" and where it will live will get resolved at link time. Later down the line, the linker sees that in foo.obj, foo::bands exists, and all references to foo::bands can be resolved.
My understanding is that you would only need to declare Foo::bands if you planned on using it prior to ever creating an instance of your class. Basically, when you declare a static in a C++ class then only one copy of that variable exists for all instances of that class. However, you can't normally access Foo::bands until an instance of the class is declared.
For example:
Pointers to Members
#include <iostream>
using namespace std;
class X {
public:
int a;
void f(int b) {
cout << "The value of b is "<< b << endl;
}
};
int main() {
// declare pointer to data member
int X::*ptiptr = &X::a;
// declare a pointer to member function
void (X::* ptfptr) (int) = &X::f;
// create an object of class type X
X xobject;
// initialize data member
xobject.*ptiptr = 10;
cout << "The value of a is " << xobject.*ptiptr << endl;
// call member function
(xobject.*ptfptr) (20);
}

Using static variable along with templates

I have a template class defined in a header file like this. Here I have defined a static variable as well:
#ifndef TEST1_H_
#define TEST1_H_
void f1();
static int count;
template <class T>
class MyClass
{
public:
void f()
{
++count;
}
};
#endif
And I have defined main() function in a different cpp file like this:
int main(int argc, char* argv[])
{
MyClass<int> a;
a.f();
f1();
cout<<"Main:" << count << "\n";
return 0;
}
I have implemented function f1() in a different cpp file like this:
void f1()
{
MyClass<int> a;
a.f();
cout<<"F1: " <<count <<"\n";
}
When I compiled this using VC6, I got the output as "F1:0 Main:2". How is this possible? Also, in general how should I handle if I want to use static variables along with templates?
You're getting two copies of the same variable because you've declared a static variable in a header file. When you declare a global variable static this way, you're saying it's local to the compilation unit (the .o file). Since you include the header in two compilation units, you get two copies of count.
I think what you really want here is a static template member variable associated with each instance of the template class. It would look like this:
template <class T>
class MyClass
{
// static member declaration
static int count;
...
};
// static member definition
template<class T> int MyClass<T>::count = 0;
This will get you a count for each instantiation of your template. That is, you'll have a count for MyClass<int>, MyClass<foo>, MyClass<bar>, etc. f1() would now look like this:
void f1() {
MyClass<int> a;
a.f();
cout<<"F1: " << MyClass<int>::count <<"\n";
}
If you want a count for all instantiations of MyClass (regardless of their template parameters), you do need to use a global variable.
However, you probably don't want a global variable directly because you run the risk of using it before it gets initialized. You can get around this by making a global static method that returns a reference to your count:
int& my_count() {
static int count = 0;
return count;
}
Then accessing it from within your class like this:
void f() {
++my_count();
}
This will ensure that count gets initialized before it's used, regardless of which compilation unit you access it from. See the C++ FAQ on static initialization order for more details.
Putting the static declaration in a header file will cause each .cpp file to get its own version of the variable. So the two cout statements are printing different variables.
Were you expecting "F1:1 Main:1"? You instantiated MyClass<int> in two separate translation units (i.e. two object files), and the linker saw that there was a duplicate template instantiation, so it discarded the instantiation that was in f1's object file.
Are you passing /OPT:ICF or /OPT:REF to the VC6 linker? That might be related to the duplicate template instantiation removal (or not; duplicate template instantiations might be a special case, compared to ordinary duplicate functions). GCC seems to do something similar on some platforms.
Anyway, I wouldn't rely on this behavior being consistent across compilers. Also, changing the order of object files on the linker command line might affect which instantiation gets discarded.
There is another solution, you can create a shared parent class and put this static variable in it, then make your template class inherit it privately, here's an example:
class Parent
{
protected:
static long count;
};
long Parent::count = 0;
template<typename T>
class TemplateClass: private Parent
{
private:
int mKey;
public:
TemplateClass():mKey(count++){}
long getKey(){return mKey;}
}
int main()
{
TemplateClass<int> obj1;
TemplateClass<double> obj2;
std::cout<<"Object 1 key is: "<<obj1.getKey()<<std::endl;
std::cout<<"Object 2 key is: "<<obj2.getKey()<<std::endl;
return 0;
}
Output will be:
Object 1 key is: 0
Object 2 key is: 1
I think this is actually undefined behaviour.
According to C++14 [basic.def.odr]/6:
There can be more than one definition of a [...] member function of a class template [...] in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
each definition of D shall consist of the same sequence of tokens; and
in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a non-volatile
const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the object is not odr-used, and the object has the same value in all definitions of D; [...]
The problem is that in the first .cpp file, the name count within f1 refers to a different object than the name count within f1 in the second .cpp file, thus violating the condition that corresponding names should refer to the same entity.
They are different objects because of the static specifier which says that each translation unit gets its own object with that name.