Using static variable along with templates - c++

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.

Related

How to have TU-specific function template instantiation?

Let's say:
Some header h.hpp defines a template function f() using sizeof on its template parameter.
Two different C++ source files, a.cpp and b.cpp, define their own structure having the same name S.
Both a.cpp and b.cpp use f() with their own S.
In other words:
h.hpp:
template <typename T>
int f()
{
return something + sizeof(T);
}
a.cpp:
#include "h.hpp"
struct S {
int a;
int b;
};
int aFunc()
{
return f<S>();
}
b.cpp:
#include "h.hpp"
struct S {
int w;
int x;
int y;
int z;
};
int bFunc()
{
return f<S>();
}
Here, within the same program, both aFunc() and bFunc() return the same value. This is because both structures are named S, and only one template function instantiation is kept.
My working solutions so far are:
Name the structures differently.
Make f() static.
Make f() part of an anonymous namespace.
Make both structures part of their own anonymous namespace.
Can you think of anything else to avoid this issue which only manifests at run time?
I need to end this.
Considering the comments of n. 1.8e9-where's-my-share m. and VainMan: such a program is indeed ill-formed (ODR violation).
Therefore, the only legal solutions are those (1 and 4):
Name the structures differently.
Make both structures part of their own anonymous namespace.
I somehow stopped reading the One Definition Rule section at:
There can be more than one definition in a program of each of the following: class type, enumeration type, inline function, inline variable (since C++17), templated entity (template or member of template, but not full template specialization), as long as all of the following is true:
each definition appears in a different translation unit
But there's another important condition:
each definition consists of the same sequence of tokens (typically, appears in the same header file)
This is obviously not my case.
The outcome of not satisfying any of those conditions is:
Otherwise, the program is ill-formed, no diagnostic required.

calling static member of class pass a parameter and get return value [duplicate]

I just wrote a class with some static data members, but now I am getting errors about "undefined references". Why doesn't this work? What am I doing wrong?
_(Note: This is meant to be an entry to [Stack Overflow's C++ FAQ](https://stackoverflow.com/questions/tagged/c++-faq). If you want to critique the idea of providing an FAQ in this form, then [the posting on meta that started all this](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag) would be the place to do that. Answers to that question are monitored in the [C++ chatroom](https://chat.stackoverflow.com/rooms/10/c-lounge), where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)_
To understand this, you should have a good understanding of compiling and linking, and the differences between declarations and definitions.
Consider the following class:
//In header file
class Example {
static bool exampleStaticMember;
};
Here, exampleStaticMember is declared but not defined. This means that if exampleStaticMember is used in a way that means that it must have an address then there must be a separate definition for it. In general, no declaration of a static data member in a class definition is a definition of that member.
The required declaration is usually put in the cpp file which contains the other definitions for the members of the class. It must be in the same namespace as the class definition. The definition typically looks like:
//In source file:
//This may optionally have an initialiser (eg "= true")
bool Example::exampleStaticMember;
The definition can be put in any cpp file, but it should not be put in the header with the class, because that would be likely to break the One Definition Rule.
As a special case, if the static member variable is an const integral or enumeration type then it can have an initialiser in the class definition:
//In header file
class Example {
static const int initialised = 15;
};
In this case, the definition in the cpp file is still required, but it is not allowed to have an initialiser:
//In source file
//Note: no initialiser!
const int Example::initialised;
Static members that have been initialised like this can be used in constant expressions.
Templates
For a static data member of a template, things are slightly different. The static member should be defined in the header along with the rest of the class:
//In header file
template<typename T>
class Example {
static int exampleInt;
static T exampleT;
}
template<typename T> int Example<T>::exampleInt;
template<typename T> T Example<T>::exampleT;
This works because there is a specific exception to the One Definition Rule for static data members of class templates.
Other uses of static
When the static keyword is applied to functions and objects that are not in a class scope it can take on a very different meaning.
When applied to objects in a function scope, it declares an object that is initialised in the first execution of the function and that subsequently keeps its value between function calls.
When applied to objects or functions at namespace scope (outside of any class or function definition), it declares objects or functions with internal linkage. This usage is deprecated for objects, as the unnamed-namespace provides a better alternative.
You have to instantiate static members defined in a header in a .cpp file. For example:
// foo.h
class foo {
static int X;
};
// foo.cpp
#include "foo.h"
int foo::X = 0;

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

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.

How to use static variable in a C++ class template

This is an example taken from geeksforgeeks. I don't understand the following code.
template<class T> int Test<T>::count = 0;
Is count an external variable? Why not just let static int count = 0?
The description and code in the geeksforgeeks is listed below.
Class templates and static variables: The rule for class templates is
same as function templates Each instantiation of class template has
its own copy of member static variables. For example, in the following
program there are two instances Test and Test. So two copies of static
variable count exist.
#include <iostream>
using namespace std;
template <class T> class Test
{
private:
T val;
public:
static int count;
Test()
{
count++;
}
// some other stuff in class
};
template<class T>
int Test<T>::count = 0;
int main()
{
Test<int> a; // value of count for Test<int> is 1 now
Test<int> b; // value of count for Test<int> is 2 now
Test<double> c; // value of count for Test<double> is 1 now
cout << Test<int>::count << endl; // prints 2
cout << Test<double>::count << endl; //prints 1
getchar();
return 0;
}
Every time you instantiate Test object with new type, a new class from available template is created for you. (So in your case, there Test<int> and Test<double> classes created on demand for you by the compiler). You can now think of Test<int> and Test<double> as 2 separate classes created from the same template.
Because there are two classes, there are two copies of static variable with same name in different scopes. template<class T> int Test<T>::count = 0; is a template for the definition of this count in classes created on demand.
If you specialize this definition for some type, for ex:
template<>
int Test<int>::count = 5;
Test<int>::count would be 7 at the time of print it. While Test<double>::count would remain 1 (unchanged).
count is not an external variable. The reason why it is outside the class like that is because the variable needs to be allocated (and maybe instantiated). When a static variable is inside a class definition, it only tells the compiler "there is going to be this kind of variable" but since definitions may be included in many source files the compiler won't do any allocations.
When the compiler sees the external definition it knows to allocate space for it and instantiate it if it is an object. This may happen only once, so it cannot be in a header file.
Class Test is a template class, meaning the compiler will generate different code each time it encounters code that instantiates a Test with a different type.
Count is not an external variable; it is a static variable.
There is one instance of a static variable shared by all instances of their container classes.
The twist here is that Test is a template class, so there is not really just one "class Test". There are two: the main() function will cause the compiler to generate "class Test" and "class Test".
As noted a static variable is shared by all instances of their container classes. As also noted, there are two generated types of class Test (int and double). Because count is a static variable, this means there needs to be one instance of count per type of Test. Therefore the compiler will generate both:
int Test<int>::count = 0;
and
int Test<double>::count = 0;
Keep in mind that the purpose of templates is that you write code once and rely on the compiler to generate code for all the different data types for which that template is used.

Why should types be put in unnamed namespaces?

I understand the use of unnamed namespaces to make functions and variables have internal linkage. Unnamed namespaces are not used in header files; only source files. Types declared in a source file cannot be used outside. So what's the use of putting types in unnamed namespaces?
See these links where it's mentioned that types can be put in unnamed namespaces:
Superiority of unnamed namespace over static?
Unnamed/anonymous namespaces vs. static functions
Why an unnamed namespace is a "superior" alternative to static?
Where do you want to put local types other than the unnamed namespace? Types can't have a linkage specifier like static. If they are not publicly known, e.g., because they are declared in a header, there is a fair chance that names of local types conflict, e.g., when two translation units define types with the same name. In that case you'd end up with an ODR violation. Defining the types inside an unnamed namespace eliminates this possibility.
To be a bit more concrete. Consider you have
// file demo.h
int foo();
double bar();
// file foo.cpp
struct helper { int i; };
int foo() { helper h{}; return h.i; }
// file bar.cpp
struct helper { double d; }
double bar() { helper h{}; return h.d; }
// file main.cpp
#include "demo.h"
int main() {
return foo() + bar();
}
If you link these three translation units, you have mismatching definitions of helper from foo.cpp and bar.cpp. The compiler/linker is not required to detect these but each type which is used in the program needs to have a consistent definition. Violating this constraints is known as violation of the "one definition rule" (ODR). Any violation of the ODR rule results in undefined behavior.
Given the comment it seems a bit more convincing is needed. The relevant section of the standard is 3.2 [basic.def.odr] paragraph 6:
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member
of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) 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
[...]
There are plenty of further constraints but "shall consist of the same sequence of tokens" is clearly sufficient to rule out e.g. the definitions in the demo above from being legal.
So what's the use of putting types in unnamed namespaces?
You can create short, meaningful classes with names that maybe used in more than one file without the problem of name conflicts.
For example, I use two classes often in unnamed namespaces - Initializer and Helper.
namespace
{
struct Initializer
{
Initializer()
{
// Take care of things that need to be initialized at static
// initialization time.
}
};
struct Helper
{
// Provide functions that are useful for the implementation
// but not exposed to the users of the main interface.
};
// Take care of things that need to be initialized at static
// initialization time.
Initializer initializer;
}
I can repeat this pattern of code in as many files as I want without the names Initializer and Helper getting in the way.
Update, in response to comment by OP
file-1.cpp:
struct Initializer
{
Initializer();
};
Initializer::Initializer()
{
}
int main()
{
Initializer init;
}
file-2.cpp:
struct Initializer
{
Initializer();
};
Initializer::Initializer()
{
}
Command to build:
g++ file-1.cpp file-2.cpp
I get linker error message about multiple definitions of Initializer::Initializer(). Please note that the standard does not require the linker to produce this error. From section 3.2/4:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
The linker does not produce an error if the functions are defined inline:
struct Initializer
{
Initializer() {}
};
That's OK for a simple case like this since the implementations are identical. If the inline implementations are different, the program is subject to undefined behavior.
I might be a bit late for answering the question the OP made but since I think the answer is not fully clear, I would like to help future readers.
Lets try a test... compile the following files:
//main.cpp
#include <iostream>
#include "test.hpp"
class Test {
public:
void talk() {
std::cout<<"I'm test MAIN\n";
}
};
int main()
{
Test t;
t.talk();
testfunc();
}
//test.hpp
void testfunc();
//test.cpp
#include <iostream>
class Test {
public:
void talk()
{
std::cout<<"I'm test 2\n";
}
};
void testfunc() {
Test t;
t.talk();
}
Now run the executable.
You would expect to see:
I'm test MAIN
I'm test 2
What you should see thought is:
I'm test MAIN
I'm test MAIN
What happened?!?!!
Now try putting an unnamed namespace around the "Test" class in "test.cpp" like so:
#include <iostream>
#include "test.hpp"
namespace{
class Test {
public:
void talk()
{
std::cout<<"I'm test 2\n";
}
};
}
void testfunc() {
Test t;
t.talk();
}
Compile it again and run.
The output should be:
I'm test MAIN
I'm test 2
Wow! It works!
As it turns out, it is important to define classes inside unnamed namespaces so that you get the proper functionality out of them when two class names in different translation units are identical.
Now as to why that is the case, I haven't done any research on it (maybe someone could help here?) and so I can't really tell you for sure. I'm answering purely from a practical standpoint.
What I would suspect though is that, while it is true that C structs are indeed local to a translation unit, they are a bit different from classes since classes in c++ usually have behavior assigned to them. Behavior means functions and as we know, functions are not local to the translation unit.
This is just my assumption.