Why does this template function not behave as expected? - c++

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?

Related

Is it possible to add class template specialization and effect previous usages of this class?

I have some header file with declared template class and template function:
print.h:
template<typename T> struct Printer {
static void print();
};
template<typename T> void print();
In the implementation file, I have some base implementation of Printer, some specializations of it, and implementation of the function print that calls Printer<T>::print.
print.cpp
template<typename T> void Printer<T>::print() {
cout << "base";
}
template<> struct Printer<int> {
static void print() {
cout << "int";
}
};
template<> struct Printer<bool> {
static void print() {
cout << "bool";
}
};
template<typename T> void print() {
return Printer<T>::print();
}
In another file, I add one more specialization of Printer and a call of function print after it.
another.cpp
template<> struct Printer<char> {
static void print() {
cout << "char";
}
};
void printChar() {
print<char>();
}
Which Printer<T>::print does printChar call? Base or specialization Printer<char>? Can I change the behavior of printChar in this way?
(print.cpp is compiled first)
I compiled this code in a single file in the same order and called printChar. The output is 'char'. But I am not sure that it will work in different files as I described. Because for me it looks like it opens the ability to extend existing code by something like a cheating injection. But maybe it is OK to practice (Swift is based on a similar kind of extensions). If it works, Is it ok to practice it?
I'm not sure which previous usages you're referring to. I see only one usage of print<char>, after the specialization of print<char>.
Templates work kind of like #define, they stamp out definitions on-demand as needed. So the right template specialization definition had better be available at the time the code needs to be stamped out, which by the way takes place independently per TU. And these definitions must be identical across TU's.
See [temp.expl.spec]/pp.6-7:
6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
7 The placement of explicit specialization declarations ... can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
So as long as print<char> is instantiated after the specialization of print<char> in every translation unit where it is used (including implicit instantiations), the program is fine. The printChar() case is OK. But if print<char> happens to be instantiated in any other TU, the program would become ill-formed NDR.
For this reason all specializations are usually bundled (included) in the same header file that declares the primary template. It might increase compile times but can save a lot of headache during program development and maintenance later on.

Can Template Specializations go in my .cpp?

Lets say that I have this:
struct foo {
template <typename T>
void bar(const T param) { cout << param << endl; }
};
Now I want to add the specialization:
template <>
void bar<char>(const char param) { cout << static_cast<int>(param) << endl; }
Can I just add the declaration to the header that foo is declared in and defince bar<char> in the implementation file foo is implemented in?
The reason that I'm asking is that locally I'm seeing it work both ways. I think the difference is: Specialized template methods that I'm only using internally to the defining class can be defined in the implementation. Specialized template methods I'm using externally seem to need to be defined in the header. I haven't been able to find anything conclusive on this though so I thought I'd ask.
The one thing thy shan't do is to declare specialization in .cpp file. There are good reasons for it, discussed in
Explicit specialization of member function template in source file
However, if you put declaration in header file (as I understand you intend to do), the specialization can go into .cpp file, as long as it is called from there at least once - and than you can have calls to the specialization outside of the translation units.
The reason for at least one requirement is that compiler is only going to instantiate the template if it is called and the definition is available, but once template is instantiated, it can be used from any translation units.

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?

No generated code for explicitly specialized template even with explicit instantiation

I'm getting consistent behavior from both gcc 4.8.3 and clang 3.2, but do not understand why it is happening. Despite the fact that I have an explicit instantiation for a class template, the code is not being generated and I get an undefined symbol when I am using a fully specialized instance of the template.
I have a simple class template definition in a file 'temp.hpp'
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C () = default;
void print ();
private:
T1 d_c;
};
Note that the method 'print()' is declared, but not defined here. I want the definition in the .cpp file and it will be specialized for different types.
So in the temp.cpp file I have the default definition of the print() method
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print ()
{
std::cout << "Printing: " << d_c << std::endl;
}
followed by a specialization of the class for the type 'float':
template <>
class C <float>
{
public:
C (float f) : d_f(f) {};
~C () = default;
void print ()
{
std::cout << "float: " << d_f << std::endl;
}
private:
float d_f;
};
and since the definitions are in the .cpp file I must explicitly instantiate all the specializations that I will be using. So I have:
template class C<int>;
template class C<float>;
The driver for my test looks like this in test.cpp:
#include "temp.hpp"
int main()
{
int i = 1;
C<int> c_int(i);
float f = 1.2;
C<float> c_float(f);
c_int.print();
c_float.print();
}
Upon compiling and linking this I get error:
test.cpp: undefined reference to `C<float>::print()'
The object code for the C< int > is properly generated. I can see it using nm:
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
As I mentioned earlier, this is consistent with gcc and clang so I'm assuming there is some language rule I don't understand here.
Note that if I add a usage of the print() method in file temp.cpp, then the code is generated, but that is silly and in my real code would be impossible. For this simple test case it would look like:
void foo ()
{
C<float> s(1.3);
s.print();
}
In the real code which motivated this little test my template has 3 template arguments which combine to expand into about 30 permutations of the code. There are one or two of those for which I need a specialization which does something different, but the other 28 I can leave alone.
Any pointers on where I've gone wrong or a language reference for why the explicit instantiation of should not generate code are greatly appreciated. I've spent 1/2 a day reading all the other stackoverflow posts on explicit instantiation and believe I am using it correctly.
From [temp.expl.spec]:
If a template, a member template or a member of a class template is explicitly specialized then that specialization
shall be declared before the first use of that specialization that would cause an implicit instantiation
to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and either the specialization is used in a way
that would cause an implicit instantiation to take place or the member is a virtual member function, the
program is ill-formed, no diagnostic required.
We're explicitly specializing C in temp.cpp, but in test.cpp, it is not declared before it is used. Thus, your code is ill-formed, no diagnostic required. You'll have to simply move the declaration of C<float> into temp.hpp
Always be careful with explicit specializations. The standard takes them very seriously:
The placement of explicit specialization declarations for function templates, class templates, [...], can affect whether a program is well-formed according
to the relative positioning of the explicit specialization declarations and their points of instantiation
in the translation unit as specified above and below. When writing a specialization, be careful about its
location; or to make it compile will be such a trial as to kindle its self-immolation.

can compiler tell me which overloaded or template function it chose?

Specifically using g++ on linux, is there a way to determine which overloaded or template function was chosen for a particular statement?
More specifically, I don't assume that I necessarily know all the possible choices, which may be in header files coming from various libraries. And even if I did, I don't assume that I could modify the relevant code.
I don't know of a way to do this directly.
The simplest solution is to set a breakpoint at the call site and single-step into whatever function is called; your debugger can then tell you which function you're in.
An IDE like Eclipse CDT can do overload and template resolution itself (if everything works right), so right-clicking on a function call and going to the function declaration will take you to the appropriate function.
By deliberately creating an ambiguous function call, as described in this answer, you can get a list of all available overloads and templates and can probably figure out which one is being invoked from there.
As Matthieu M. said, Clang can dump its AST. This requires some interpretation, but it can help you figure out which function is being called.
Partial answer.
You can use non standard macro for printing name of function in run-time (Macro / keyword which can be used to print out method name?
For GNU C++:
#include <iostream>
using namespace std;
template <typename T>
void f(const T & t)
{
cout << __PRETTY_FUNCTION__ << endl;
}
void f(const string &)
{
cout << __PRETTY_FUNCTION__ << endl;
}
void f(int)
{
cout << __PRETTY_FUNCTION__ << endl;
}
int main()
{
f(1.0);
f(1);
f(string("sss"));
string a;
f(a);
}
Output from this code (http://ideone.com/PI39qK):
void f(int)
void f(int)
void f(const std::string&)
void f(T&) [with T = std::string]