What has the meaning the "using of template keyword in the function declaration"?
In this example compiler errors with error: "func" is not a template function.
template<typename T>
struct Window {
T value;
};
template void func(Window<int>, int);
template<typename T>
void func(Window<T>, T) {
}
int main(void) {
}
But below example is ok.
template<typename T>
struct Window {
T value;
};
template<typename T>
void func(Window<T>, T) {
}
template void func(Window<int>, int);
int main(void) {
}
What is the meaning with "template" in the above case?
Is it just indicator that this function is template function?
A declaration that begins with the keyword template and does not have the <pointy braces> immediately afterward is called an explicit instantiation. It means to look up the template definition and plug in the specified template parameters to get a specific function specialization or class specialization. So in the first example, the compiler is complaining it can't instantiate func(Window<int>, int) because it doesn't yet know anything about a template called func.
Explicit instantiations are usually not necessary, since templates can be implicitly instantiated just by attempting to use them. But explicit instantiation gives some control over where and how related linker symbols appear, and can in some cases be used to move a template definition out of a header file into a source file.
This is just because in your first example you have the definition of the template
template<typename T>
void func(Window<T>, T) {
}
after the forced instantiation that's represented by this line:
template void func(Window<int>, int);
Whereas in the second example they're the right way around.
But the comment to your question is fair, you are asking a basic question ('what does template mean'), which is best answered by a thoroughgoing study of the subject.
Related
I have two template class, and the Leaf<T> is derived from the Base<T>, then I developed a template function which uses the reference of the Base<T> as its parameter. And set the definition and the instantiation of that function in its source file.
The issue happened once I tried to pass the Leaf<T> as the argument of that function. The compiler tries to find the symbol with Leaf<T> without the auto convention as it used to be.
// foo.h
#ifndef __FOO_H_INCLUDED__
#define __FOO_H_INCLUDED__
#include <base.h>
template <typename T>
void Foo(T &value);
#endif // __FOO_H_INCLUDED__
// foo.cpp
#include <foo.h>
#include <iostream>
template <typename T>
void Foo(T &value)
{
std::cout<<value.getValue()<<std::endl;
}
template void Foo(MyBase<int> &value);
// main.cpp
#include <leaf.h>
#include <foo.h>
int main()
{
int i = 20;
MyLeaf<int> leaf;
leaf.setValue(i);
Foo(leaf);
}
The above snippet will throw an "undefined reference" exception in linking. Refactor the invoking as Foo<MyBase<int> >(leaf) will fix the issue but that not what I want. And explicitly instantiate all of the potential derived types is also impossible because there is no way to know how many are them.
So is there a way that could make the linker recognize my symbols with the base type rather than find the precise one and throw an error?
Adding an explicit template instantiation in one translation unit must be paired with an explicit template instantiation declaration to make sure the compiler doesn't try to do an implicit instantiation. Otherwise, the program is ill-formed.
Beyond that, you can't have template argument deduction deduce anything other than Foo<MyLeaf<int>> the way you have it setup. But with a bit of tweaking, we can have it working. In your header:
template <typename T>
void Foo(MyBase<T> &value);
extern template void Foo(MyBase<int> &value);
And in your implementation file:
template <typename T>
void Foo(MyBase<T> &value)
{
std::cout<<value.getValue()<<std::endl;
}
template void Foo(MyBase<int> &value);
Now the deduction rules, and overload resolution should match the functions correctly. What we did is shift the burden. Now that function always expects a class instantiated from MyBase. And since every class instantiated from MyLeaf is also derived from one instantiated from MyBase, you see where it goes. We fulfill the templates requirement for the argument, and just leave it to deduce T from it.
This question was at the interview:
Does this code causes any compile/linking errors and why so?
template <int T> void f();
template <> void f<0>() {}
void test()
{
f<1>();
}
Please explain the behaviour. Thanks a lot.
template<> void f<0>() {}
is specialization of function template for argument 0, if you call f<0>() this version of function will be called.
This code is incorrect, it cause linking errors, since there is no specialization for f<1> and template version of function is not defined.
It will compile (all the code is gramatically valid) but will fail at link stage.
This is because template <int T> void f(); is declared but not defined, the <0> specialisation is defined but that makes no odds to you since you're not instantiating it.
Actually, it would be possible for the <0> specialisation to contain syntax errors and the program would still compile without error! This is because formally, templates are only compiled if they are used. (I wouldn't expect a candidate to have the presence of mind during interview conditions to point that out.)
It will compile because compiler can see a declaration for a generic template. There is a fully specialized template for 0 also. But we are calling it for 1, which will try to invoke the generic template, but since linker cannot find any definition for the general template, the program will show linker error.
Soloution
template <int T> void f();
template <> void f<0>() {}
template <int T> void f() { }
void test()
{
f<1>();
}
The following bit of code fails to compile on gcc 4.5.3
struct Frobnigator
{
template<typename T>
void foo();
template<typename T>
void bar();
};
template<typename T>
void Frobnigator::bar()
{
}
template<typename T>
void Frobnigator::foo()
{
bar<T>();
}
template<> // error
void Frobnigator::foo<bool>()
{
bar<bool>();
}
template<>
void Frobnigator::bar<bool>()
{
}
int main()
{
}
Error message: specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation. I finally resolved this problem by having the specialization of Frobnigator::bar<bool>() appear before Frobnigator::foo<bool>(). Clearly the order in which the methods appear matter.
Why then is the following lite version of the above code, in which the the specialization of bar appears after the generic version, valid ?
struct Frobnigator
{
template<typename T>
void foo();
};
template<typename T>
void Frobnigator::bar()
{
}
template<>
void Frobnigator::bar<bool>()
{
}
int main()
{
}
Your first code is not correct by standard.
n3376 14.7.3/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.
In your case - implicit instantiation of bar function with type bool is required by its usage in foo<bool>, before explicit specialization declaration.
Clearly the order in which the methods appear matter.
Indeed; as is usually the case in C++, you can't use something before it's declared, and this applies to explicit template specialisations as well as most other things.
Using bar<bool> (by calling it from foo<bool>) without a previous declaration of an explicit specialisation causes that specialisation to be instantiated from the generic template, if it hasn't already been. You'll need at least a declaration of the explicit specialisation to prevent that.
Why is this the case, considering that the specialization of bar appears after the generic version in the following lite version of the above code
The second example differs by not instantiating foo<bool> at all. The issue isn't that the specialisation is declared after the generic template (which must be the case), but that it's declared after that specialisation has already been instantiated.
Declaring template function friends involves some incredibly unintuitive syntax, even for C++! What is the rationale behind the choice of syntax for the extra <> needed? Wouldn't it make more sense to use the template keyword?
For those that don't know about this, here is an example of what you might try to do:
template <typename T>
class Foo
{
int x;
friend void bar(Foo<T>);
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
If you try to call bar(Foo<T>()), you will get linker errors.
To solve this, you have to forward declare bar (and therefore Foo) and then stick an oddly placed <> in the friend declaration.
template <typename T> class Foo;
template <typename T> void bar(Foo<T>);
template <typename T>
class Foo
{
int x;
friend void bar<>(Foo<T>); // note the <> (!?)
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
My question is, what is the rationale behind the <> syntax? Wouldn't it be more intuitive to use the template keyword or something along those lines?
EDIT: To clarify, I already know why the <> is required, what I want to know is why they chose to use <> to disambiguate it instead of some other more intuitive syntax.
Wait. You are not declare a friend template. You declare a specialization of a template as friend! As such, why would you want to put a template clause there?
The syntax to name specializations of function templates is by teplateName<ArgumentList>, and that is what you shall use according to the Standard in the friend declarations.
If you want to befriend the whole template and all specializations generated and explicitly specialized, you can still do that, and then you can use a template clause
template<typename U>
friend void bar(Foo<U>);
Quoting this page:
The non-template function is called because a non-template function takes precedence in overload resolution.
So my guess the friend void bar<>(Foo<T>); is intuitive because you want to make sure it's the template function you are calling and not an overload for Foo<T>. There would otherwise no way for the compiler to notice if the templated or the non-templated function is the class'es friend.
Why the <> syntax is used and not the template syntax is not clear to me.
I am looking at some c++ code and do not understand the purpose of the template declaration in this situation:
template<> void operator>>(const ClassA& s, const ClassB d) {...}
What is the semantic of template<>?
This is, indeed, template specialization, as others before mentioned. There must be some previously declared function template, such as:
template<typename T, typename U>
void operator>>(const T& s, const U d) {...}
However, it is quite misguided. It is much better to remove the template<> altogether, so operator>> would just be overloaded. The problem with function template specialization is that it may lead to unexpected behaviour in the presence of overloaded functions (and operator>> has lots of overloads), since the specialization does not overload. This means that the compiler first selects the most appropriate overload for the function and then, if the selected overload is a function template, it looks for template specializations to see if there is an appropriate one.
A classical example (unfortunately, I don't remember where I read it). Consider this overloaded function template:
template <typename T>
void Function(T param);
template <typename T>
void Function(T* param);
template <>
void Function(int* param);
main()
{
int i = 5;
Function(&i);
}
As expected, the template specialization for int* is called. But just change the order of the function definitions:
template <typename T>
void Function(T param);
template <>
void Function(int* param);
template <typename T>
void Function(T* param);
main()
{
int i = 5;
Function(&i);
}
Now the general template for T* is called, since we are specializing the template for T, not for T*, and this second template is better suited for our call. This would be avoided if we overloaded the function instead of specializing the template:
void Function(int* param);
Now the order of declaration does not matter, we will always call the overload for int*.
UPDATE: Now I know who to credit. I read about this in an article by Herb Sutter. The example was provided by Peter Dimov and Dave Abrahams.
This is Template specialization
You use this syntax when you want to provide a special handler for a particular template type. Consider:
// A normal template definition.
template <typename AType>
whoami () { std::cout << "I am an unknown type."; }
// Now we specialize.
template <>
whoami<int> () { std::cout << "I am an integer!"; }
There's some other nonsense involved, particularly "partial specialization", but that's the basic function of template <>.
It is a template specialization: (fully or partially) resolving the template for a specific type. (Your particular example seems to be a full specialization, as no more template parameters are left unresolved in it. If the template has multiple parameters, and you specialize only some of them, it is called partial template specialization)
This allows one to provide type-specific optimizations for a given template, or to do many clever tricks such as detecting the static type of variables etc.