"template<>" vs "template" without brackets - what's the difference? - c++

Suppose I've declared:
template <typename T> void foo(T& t);
Now, what is the difference between
template <> void foo<int>(int& t);
and
template void foo<int>(int& t);
semantically? And do template-with-no-brackets and template-with-empty-brackets have other semantics in other contexts?
Related to:
How do I force a particular instance of a C++ template to instantiate?

template <> void foo<int>(int& t); declares a specialization of the template, with potentially different body.
template void foo<int>(int& t); causes an explicit instantiation of the template, but doesn't introduce a specialization. It just forces the instantiation of the template for a specific type.

With class/struct,
template <typename T> struct foo {};
Following is a specialization:
template <> struct foo<int>{};
Following is an explicit instantiation:
template struct foo<int>;

Related

Specializing with two template arguments for an argument (C++ template)

I have no idea how to describe this question properly, but basically what I want to know is something like this can be compiled without a problem:
// prototype
template <class T>
void pretty_function(T arg);
// specialization
template <class U, class V>
void pretty_function<U<V>>(T arg);
So I want to specialize the type T with the type U< V >, where the type U requires a template argument V. I think I can easily test this on my local workstation, but I just leave it here for the future reference.
It sounds like you want to declare a specialization of pretty_function that would accept only types of the form U<V> where U can be any class template and V can be any type. This would be a partial specialization since the template argument T is not fully specified. C++ does not support partial specialization of function templates. The usual workaround is to dispatch to a helper class template that can be partially specialized:
namespace detail {
template <class T>
struct pretty_function_helper {
static void doit(T arg) { /* implementation */ }
};
// partial specialization
template <template <class> class U, class V>
struct pretty_function_helper<U<V>> {
static void doit(U<V> arg) { /* implementation */ }
};
}
template <class T> void pretty_function(T arg) {
detail::pretty_function_helper<T>::doit(arg);
}

Template class specialization with template class

Related questions:
c++ nested template specialization with template class
template class specialization with template class parameter
Consider the following code:
template <typename T>
struct is_std_vector: std::false_type { };
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };
Why is such template class specialization syntax correct?
The following seems more logical:
template <typename T>
struct is_std_vector: std::false_type { };
template<> //--- because it is is_std_vector specialization
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };
Class template partial specialization syntax closely mirrors function template syntax. Indeed, the rules for ordering class template partial specializations is based on function template partial ordering.
The way you would write a function taking a vector<T> is:
template <class T>
void is_std_vector(vector<T> ) { ... }
So the way you write a specialization on vector<T> is the same:
template <class T>
class is_std_vector<vector<T>> { ... };
Matching the specialization of is_std_vector would try to deduce T in vector<T> from some type argument A, so it makes a lot of sense that they're written the same way.
For full specializations, we use template <> as placeholder signal to make full specializations look similar to partial specializations. I'm not sure what purpose an extra template <> would serve in this particular case.

Explicitly specialized members need their containing class templates to be explicitly specialized as well

I read in many articles, that for class template when specializing
member template, the class that containing specialized member template also shall be explicitly specialized. Is there a point about it in standard and is there any reason to have such restriction?
I mean under the hood.
Why this is not allowed.
template <typename T>
class A
{
template <typename U>
void foo()
{}
};
template <typename T>
template <>
void A<T>::foo<int>()
{}
[temp.expl.spec]/16:
In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope, the
member template and some of its enclosing class templates may remain
unspecialized, except that the declaration shall not explicitly
specialize a class member template if its enclosing class templates
are not explicitly specialized as well. [ Example:
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template <> template <class X>
class A<int>::B {
template <class T> void mf1(T);
};
template <> template <> template<class T>
void A<int>::B<double>::mf1(T t) { }
template <class Y> template <>
void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized
// but its enclosing class template A is not
— end example ]

Specialize templated function for templated class

In C++, I am trying to specialize a templated function for a object that is templated itself.
Here is a basic example:
test.h:
template <class T>
class myC {
T x;
};
template <class U>
void f(U y) {
}
template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}
test.cpp
#include "test.h"
int main() {
myC<double> m;
f(m);
}
GCC 4.6.1 gives me the following error message:
In file included from test.cpp:1:0:
test.h:13:25: error: too many template parameter lists in declaration of ‘void f(myC<T>)’
test.h:13:6: error: template-id ‘f<myC<T> >’ for ‘void f(myC<T>)’ does not match any template declaration
test.h:13:25: note: saw 2 ‘template<>’, need 1 for specializing a member function template
Is this at all possible? Or is there another way to accomplish the same goal?
template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}
What you're atttempting to be doing here is called partial specialization which is not allowed in case of function template.
A function template is either fully specialized, or not specialized at all. No partial specialization of function template is allowed by the language specification.
So you can overload the function template as:
template <class T>
void f(myC<T> y) //note that it is overload, not specialization
{
}
which is allowed, and preferred over even fully specialization of template.
Read these articles by Herb Sutter:
Why Not Specialize Function Templates?
Template Specialization and Overloading
You cannot specialize a template function; only template classes can be specialized. Edit: Nawaz's answer is correct: it's partial specialization that is not allowed for template functions, only for classes. A full specialization is possible:
template <class U> void f(U y) {}
template<> void f<double>(double y) {} // specialization for double
Note that the template argument need not be explicitly specified if it can be deduced from the context:
template<> void f<>(int y) {} // specialization for int
In your case, full specialization is not possible because the function argument is a template class. However, a template function, like any function, can be overloaded. In your case, it will be like this:
template <class T>
class myC {
T x;
};
template <class U>
void f(U y) {
}
template <class T>
void f(myC<T> y) {
}
int main() {
myC<double> m;
f(m);
return 0;
}
As far as I can tell, you cannot specialize template functions, only template classes (or structs).
But that is hardly a limitation: just declare a struct with static public member functions and mave the template parameters to the struct:
template <class T>
class myC {
T x;
};
template <class U>
struct Foo
{
static void f(U y) {
}
};
template <>
template <class T>
struct Foo<myC<T> >
{
static void f(myC<T> y) {
}
};
The drawback is that class templates do not solve the template parameters automatically. But that can be easlily solved with a function template, similar to the original one:
template <class U>
void f(U y) {
return Foo<U>::f(y);
}

Why the difference in syntax between explicit and partial specialization?

Example:
template <typename T, typename U>
struct A {
void Print() {}
};
template <>
void A<int, float>::Print() {} // Okay
template <typename T>
void A<T, char>::Print() {} // Will produce error
Question:
I know that you have to define the class template partial specialization in the above code for it to work and I also know from the standard that The members of the class template partial specialization are unrelated to the members of the primary template (§ 14.5.5.3). However, why the difference in syntax between a explication specialization and a partial specialization?
You cannot specialize function templates partially, only fully.
The first instance makes use of the fact that member functions of class templates are themselves function templates, and thus the restriction applies to them.
When you partially-specialize the class template, you have an entirely new class template, which you have to define anew.
template <typename T>
void A<T, char>::Print() {} // Will produce error
You are:
re-defining a function (it has already been defined when declared void Print() {}, you see there are {}.
with a template argument list that doesn't match the declaration: template <typename T, typename U> void Print()
In fact, even if you haven't defined the function when declared it, you will still have an error since your declaration and definition do not match, the compiler will not be able to find a definition for the original template, or a declaration for the specialized template.
A specialized template function for a function that is related to a struct must have a specialized struct as well, This code works:
template <typename T, typename U>
struct A {
void Print() {}
};
template <>
void A<int, float>::Print() {} // Okay
template <typename T>
struct A<T,char>
{
void Print();
};
template <typename T>
void A<T,char>::Print() {}
Because template function has been declared in it's template struct.