In C++ Primer Plus (2001, Czech Translation) I have found these different template specialization syntax:
function template
template <typename T> void foo(T);
specialization syntax
void foo(int param); // 1
void foo<int>(int param); // 2
template <> void foo<int>(int param); // 3
template <> void foo(int param); // 4
template void foo(int param); // 5
Googling a bit, I have found only No.3 examples. Is there any difference (in call, compiling, usage) among them? Are some of them obsolete/deprecated? Why not just use No.1?
Here are comments with each syntax:
void foo(int param); //not a specialization, it is an overload
void foo<int>(int param); //ill-formed
//this form always works
template <> void foo<int>(int param); //explicit specialization
//same as above, but works only if template argument deduction is possible!
template <> void foo(int param); //explicit specialization
//same as above, but works only if template argument deduction is possible!
template void foo(int param); //explicit instantiation
Added by me:
//Notice <int>. This form always works!
template void foo<int>(int param); //explicit instantiation
//Notice <>. works only if template argument deduction is possible!
template void foo<>(int param); //explicit instantiation
From coding point of view, overload is preferred over function-template-specialization.
So, don't specialize function template:
Why Not Specialize Function Templates?
Template Specialization and Overloading
And to know the terminologies:
instantiation
explicit instantiation
specialization
explicit specialization
See this :
Difference between instantiation and specialization in c++ templates
Using Visual Studio 2012, it seems to work slightly different if there's no function argument:
template <typename T> T bar( );
//template int bar<int>( ) { return 0; } doesn't work
template < > int bar<int>( ) { return 0; } //does work
Related
Here is a code from the article Why not specialize function templates?
template<class T>
void f(T); // (1)
template<class T>
void f(T*); // (2)
template<>
void f<>(int*); // (3)
My question is about the last declaration. What does that syntax mean? When we want to fully specialize a function template, e.g. (1), for some type we usually write:
template<>
void f<int>(int);
i.e. we put that type into the angle-brackets after the function' name.
So what does the syntax (3) means?
In your case,
template<> void f<>(int*);
is an explicit specialization of
template<class T> void f(T*);
base template. It's the same as
template<> void f<int>(int*);
just the template argument is deduced.
You can even write:
template<> void f(int*);
with the same effect. A similar case is presented on cppreference, see section Explicit specializations of function templates, where there is written:
When specializing a function template, its template arguments can be omitted if template argument deduction can provide them from the function arguments.
The relevant part of the C++ Standard: http://eel.is/c++draft/temp.expl.spec#11.
A missing template argument will be deduced by the compiler if you don't provide it. In this particular case it will be deduced to int* because the second template is more specialized (but both are the candidates). So
template<> void f<>(int*)
will become
template<> void f<int>(int*)
after type deduction.
Consider the following function template declaration:
template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
void foo(T i);
There is only one possible valid instantiation of this template, namely with T = int. I'd like to put this definition in an implementation file. I can think of two possible ways of doing so. (If you're wondering why on earth I'd do this rather than just saying void foo(int i), it's because the template version prevents implicit conversions at the call site.)
Approach 1:
I can use an extern template declaration to tell other TUs that foo<int>() is instantiated elsewhere:
// In foo.hpp
template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
void foo(T i);
extern template void foo(int);
// In foo.cpp
template <typename T, typename>
void foo(T i) { ... } // full template definition
template void foo(int); // explicit instantiation with T = int
Approach 2:
I can provide an explicit specialisation for the int case:
// In foo.hpp
template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
void foo(T i);
template <> void foo(int i); // explicit specialisation declaration (*)
// In foo.cpp
template <>
void foo(int i) { ... } // explicit specialisation definition
Questions:
Are both of these approaches legal, or am I unintentionally relying on UB?
If both are legal, is there a good reason to prefer one approach over the other, other than the fact that approach 2 is very slightly less typing? Both GCC and Clang work equally well with either approach.
For approach 2, is the explicit specialisation declaration at (*) actually required? Again, both GCC and Clang are perfectly happy if it's omitted, but doing so makes me uncomfortable about the fact that a call to foo(3) in another TU is an implicit instantiation of a template with no definition visible, and no promise that such a definition exists elsewhere.
There is a third approach. In approach 3 you specify the function you want to have and the you add a template overload and mark that as delete. That looks like
void foo(int i)
{
// stuff
}
template <typename T>
void foo(T t) = delete;
Since the template version will match all types exactly it will be preferred in all cases except int since a non template exact match is preferred to a template one. So you will only be able to call foo with an int and all other types will give you an error that they are trying to call the deleted function void foo(T t).
Live Example
I have a problem concerning partial class template specialization in c++. I have one class A with two templates T,U. Then i want two class specializations with exclusive methods print_me(), only visible for those two specializations. Apart from that i need fully specialized member functions add_integer/add_double. When i implement those methods in the header file, it compiles fine. But id really like my implementations to be in the source file, which is no problem for the fully specialized functions, but for the partial ones. I get following errors for the code below:
test.h:27:25: error: declaration of ‘void A<int, U>::print_me()’ outside of class is not definition [-fpermissive]
test.h:30:28: error: declaration of ‘void A<double, U>::print_me()’ outside of class is not definition [-fpermissive]
But if i leave out the declarations of print_me() in the header file i get an undefined reference error, which i understand, as my compiler cant know, which methods to instantiate when compiling.
test.h:
//Primary Template Class
template <typename T, typename U>
class A{};
//Partial Specialization 1
template <typename U>
class A<int,U>
{
public:
void add_double(double a);
void print_me();
};
//Partial Specialization 2
template <typename U>
class A<double,U>
{
public:
void add_int(int a);
void print_me();
};
//explicit specialization
template <>
void A<int,double>::add_double(double a);
//explicit specialization
template <>
void A<double,int>::add_int(int a);
//partial specialization
template <typename U>
void A<int,U>::print_me();
//partial specialization
template <typename U>
void A<double,U>::print_me();
test.cpp
#include "test.h"
template <>
void A<int,double>::add_double(double a){}
template <>
void A<double,int>::add_int(int a){}
template <typename U>
void A<int,U>::print_me(){};
template <typename U>
void A<double,U>::print_me(){};
for testing purpose main.cpp
#include "test.h"
int main()
{
A<int,double> * a_0=new A<int,double>;
A<double,int> * a_1=new A<double,int>;
a_0->add_double(1.1);
a_0->print_me();
a_1->add_int(1);
a_1->print_me();
return 0;
}
So is there any possibility to have the print_me() methods implemented in the source file? Whats the difference between fully and partially specialized member functions in this context?
Any hints will be appreciated
as #Angew mentioned, partial specialization is still a template, which is just a blueprint for yourprint_memethod.
you need to instantiate your template function. for that you can use explicit instantiation or implicit instantiation in your test.cpp file.
Explicit Instantiation:
template
void A<double,int>::add_int(int a);
Implicit Instantiation:
just define a dummy function in test.cpp which will call the fully specialized template function print me (you don't have to use this dummy function) :
void instatiatePrintMe()
{
A<int, double> a;
a.print_me();
}
you can read here for more information: C++ - Defining class template (header/source file)
In C++ Primer Plus (2001, Czech Translation) I have found these different template specialization syntax:
function template
template <typename T> void foo(T);
specialization syntax
void foo(int param); // 1
void foo<int>(int param); // 2
template <> void foo<int>(int param); // 3
template <> void foo(int param); // 4
template void foo(int param); // 5
Googling a bit, I have found only No.3 examples. Is there any difference (in call, compiling, usage) among them? Are some of them obsolete/deprecated? Why not just use No.1?
Here are comments with each syntax:
void foo(int param); //not a specialization, it is an overload
void foo<int>(int param); //ill-formed
//this form always works
template <> void foo<int>(int param); //explicit specialization
//same as above, but works only if template argument deduction is possible!
template <> void foo(int param); //explicit specialization
//same as above, but works only if template argument deduction is possible!
template void foo(int param); //explicit instantiation
Added by me:
//Notice <int>. This form always works!
template void foo<int>(int param); //explicit instantiation
//Notice <>. works only if template argument deduction is possible!
template void foo<>(int param); //explicit instantiation
From coding point of view, overload is preferred over function-template-specialization.
So, don't specialize function template:
Why Not Specialize Function Templates?
Template Specialization and Overloading
And to know the terminologies:
instantiation
explicit instantiation
specialization
explicit specialization
See this :
Difference between instantiation and specialization in c++ templates
Using Visual Studio 2012, it seems to work slightly different if there's no function argument:
template <typename T> T bar( );
//template int bar<int>( ) { return 0; } doesn't work
template < > int bar<int>( ) { return 0; } //does work
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.