Storing value of pointer to specialized template function - c++

I would like to use some comparable representation of type, which is not direct like std::is_same<> and does not use RTTI. __PRETTY_FUNCTION__ macro gives same string for 2 different classes with same name defined in different .cpp files in anonymous namespaces and comparing strings is slow.
Let's consider such a piece of code:
template<typename T>
void func() {}
int main() {
std::cout << reinterpret_cast<size_t>(&func<int>) << std::endl;
std::cout << reinterpret_cast<size_t>(&func<float>) << std::endl;
}
Is storing numeric value of pointer to specialized template function well defined behaviour? It will not be called anywhere.
Will it have same value in different .cpp files for same specialization?
Will it have same value between dynamic linked libraries - probably not?

Related

Why does this template function not behave as expected?

I was reading about template functions and got confused by this problem:
#include <iostream>
void f(int) {
std::cout << "f(int)\n";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << " ";
f(val);
}
void f(double) {
std::cout << "f(double)\n";
}
template void g<double>(double);
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // d f(int), this is surprising
g(1); // i f(int)
}
The results are the same if I don't write template void g<double>(double);.
I think g<double> should be instantiated after f(double), and therefore the call to f in g should call f(double). Surprisingly, it still calls f(int) in g<double>. Can anyone help me understand this?
After reading the answers, I figured out what my confusion really is.
Here is an updated example. It is mostly unchanged except that I added a specialization for g<double>:
#include <iostream>
void f(int){cout << "f(int)" << endl;}
template<typename T>
void g(T val)
{
cout << typeid(val).name() << " ";
f(val);
}
void f(double){cout << "f(double)" << endl;}
//Now use user specialization to replace
//template void g<double>(double);
template<>
void g<double>(double val)
{
cout << typeid(val).name() << " ";
f(val);
}
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // now d f(double)
g(1); // i f(int)
}
With the user specialization, g(1.0) behaves as I expected.
Should the compiler not automatically do this same instantiation for g<double> in the same place (or even after main(), as described in section 26.3.3 of The C++ Programming Language, 4th edition)?
The name f is a dependent name (it depends on T via the argument val) and it will be resolved into two steps:
Non-ADL lookup examines function declarations ... that are visible from the template definition context.
ADL examines function declarations ... that are visible from either the template definition context or the template instantiation context.
void f(double) is not visible from the template definition context, and ADL will not find it either, because
For arguments of fundamental type, the associated set of namespaces and classes is empty
We can slightly modify your example:
struct Int {};
struct Double : Int {};
void f(Int) {
std::cout << "f(Int)";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << ' ';
f(val);
// (f)(val);
}
void f(Double) {
std::cout << "f(Double)";
}
int main() {
g(Double{});
}
Now ADL will find void f(Double) in the second step, and the output will be 6Double f(Double). We can disable ADL by writing (f)(val) (or ::f(val)) instead of f(val). Then the output will be 6Double f(Int), in agreement with your example.
The problem is f(double) has not been declared at the point where you call it; if you move its declaration in front of the template g, it will get called.
Edit: Why would one use manual instantiation?
(I'll talk about function templates only, analogous argumentation holds for class templates too.) The main use is to reduce compilation times and/or to hide the code of the template from users.
C++ program are built into binaries in 2 steps: compilation and linking. For the compilation of a function call to succeed only the header of the function is needed. For the linking to succeed, an object file containing compiled body of the function is needed.
Now when the compiler sees a call of a templated function, what it does depends on whether it knows the body of the template or only the header. If it only sees the header it does the same thing as if the function was not templated: puts information about the call for the linker to the object file. But if it also sees the body of the template it does also another thing: it instantiates proper instance of the body, compiles this body and puts it into the object file as well.
If several source files call the same instance of the templated function, each of their object files will contain a compiled version of the instance of the function. (Linker knows about this and resolves all the calls to a single compiled function, so there will only be one in the final binary of the program/library.) However in order to compile each of the source files the function had to be instantiated and compiled, which took time.
It's enough for the linker to do it's job if the body of the function is in one object file. To manually instantiate the template in a source file is a way to make the compiler put the body of the function into the object file of the source file in question. (It's kinda as if the function were called, but the instantiation is written in a place where function call would be invalid.) When this is done, all the files that call your function can be compiled knowing only the header of the function, thus saving time it would take to instantiate and compile the body of the function with each of the calls.
The second reason (implementation hiding) might make sense now. If a library author wants users of her template function to be able to use the function, she usually gives them the code of the template, so they can compile it themselves. If she wanted to keep the source code of the template secret she could manually instantiate the template in the code she uses to build the library and give the users the object version thus obtained instead of the source.
Does this make any sense?

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.

Why templates declared in the struct on the header dont violate ODR and specialization does?

I have this code:
#include <iostream>
struct A
{
template<typename T> bool isImplemented()
{
std::cout << "Not Implemented" << std::endl;
return false;
}
};
template<> inline bool A::isImplemented<int>()
{
std::cout << "int Implemented" << std::endl;
return true;
}
I can understand why the template specialization needs the inline, in order to prevent the ODR to be violated the inline will merge the translation table avoiding a conflict.
But, why I don`t need an inline on the isImplemented inside the struct A?
Maybe that question can be extended to, why if the method is declared inside the struct/class on the header it does not need the inline?
As I can understand, it would create the symbols on every object file (.o) that it is called, violating the ODR, why that does not happen?
You do not need it for two reasons:
Every function defined within the definition of the class is implicit inline.
A template doesn't need inline keyword. Remember, your original function is a template, while specialization is not.
The point to highlight here is that template<typename T> bool isImplemented() IS NOT a function.
It is a template to a function and will only exist (as code) once specialized, like you did with template<> inline bool A::isImplemented<int>().
The inline here is not mandatory. Program compiles and runs perfectly without it.
Strangely your struct A does not depend on any template parameter neither isImplemented() method so I am still trying to figure out your intention.
A simple usage of your functions might look like this:
int main( )
{
A a;
a.isImplemented< int >( );
a.isImplemented< double >( );
}
And the output:
int Implemented
Not Implemented
And basically you are able to tell wich specializations you have explicitly implemented from the generic ones. Is it what you need?
EDIT:
Given the comment on my answer, I believe the original question is nicely answered here:
Explicit specialization in non-namespace scope
C++ syntax for explicit specialization of a template function in a template class?

How does the compilation of a class work?

There are many references about compilation/linking process, but I am interested in a more concrete problem: compilation of a class.
The question arises because in general it is necessary to know things before you can use. For example: you can not call the function if it has not previously been declared.
In classes, it is not done in the same way. You can use a member before it appears. What the compiler does? Does the standard says something about a previous stage of compilation?
To be more specific, the following example shows how we can use members defined below.
#include <iostream>
class EvenOdd {
public:
EvenOdd(): value(0) {}
void assignEven(unsigned v) {
if (v>0 && v%2==1) {
std::cout << "Wrong call... is odd" << std::endl;
assignOdd(v);
}
else {
std::cout << "Right..." << v << " is Even" << std::endl;
value= v;
}
}
void assignOdd(unsigned v) {
if (v>0 && v%2==0) {
std::cout << "Wrong call... is even" << std::endl;
assignEven(v);
}
else {
std::cout << "Right..." << v << " is Odd" << std::endl;
value= v;
}
}
private:
unsigned value;
};
int main()
{
EvenOdd a;
std::cout << "Do it right..." << std::endl;
a.assignEven(2);
std::cout << "doing it wrong..." << std::endl;
a.assignEven(3);
}
We could also add further questions about inline functions, as may be defined after the point of call and the compiler can resolve without problems. I guess the answer is related.
UPDATE: I know the compilation/linkage has several steps. On the other hand, if the compiler accepts calling a function defined bellow is due that the compiler has analized the code in some sense. The question is ¿which kind of previous stage is done before? Moreover... in which part of the standard we find something related to use a member defined bellow?
To know how the compiler works is very interesting because it has to know details about the function bellow (at least, the header) that seems to correspond actually to compile. Even the data member has to be compiled because you have to relate its type in the context of the function above
It works like the code is reordered but it is not consistent with the example above because both function members call each other. It is like reordering data members and header of functions could be the code that is considered by the compiler.
The standard says
A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
This in particular means that a member function body may refer to class members declared below it. The standard doesn't care how implementations achieve this. One possible method would be to postpone semantic analysis of member function bodies and other elements specified above until the closing brace of the class is seen.
Functions within classes can access and modify (unless the function is constant) data members without declaring them, because the data members are already declared in the class. In your response to why function do not need declaration in class.

C++ inline class definition and object initialisation

I've just come across the following code:
#include <iostream>
static class Foo
{
public:
Foo()
{
std::cout << "HELLO" << std::endl;
}
void foo()
{
std::cout << "in foo" << std::endl;
}
}
blah;
int main()
{
std::cout << "exiting" << std::endl;
blah.foo();
return 0;
}
I haven't seen the above method of definining a variable before - the class definition is done inline with the variable definition. It reminds me of anonymous classes in Java. What is this called, and is it in the C++ standard?
Thanks
Taras
It's quite standard to define a class (or struct, perfectly equivalent except that the default is public instead of private) and declare a variable of its type (or pointer to such a variable, etc) -- it was OK in C (with struct, but as I already mentioned C++'s class, save for public vs private, is the same thing as struct) and C++ mostly maintains upwards compatibility with (ISO-1989) C. Never heard it called by any special name.