Is function template specialization really allowed?

Viewed 98

As per this article, which says that( emphasis mine ):

Partial template specialization allows us to specialize classes (but not individual functions!)

It seems that function partial template specialization is not allowed. Is that really correct?

What confuses me is that why these code snippets could be compiled successfully:

//demo1.cpp
//first code snippet(https://coliru.stacked-crooked.com/a/0868610b5be94f2c)
//Why this function template specialization compiles? 
//Because this is full template specialization other than partial template specialization?Am I right?
#include <iostream>
#include <string.h>
using namespace std;

template <class T>
void f(T)
{ 
    T d; 
    std::cout <<"first one" << std::endl;
}
    
template <>
void f<int>(int)
{ 
    int d;
    std::cout <<"second one" << std::endl;
}

int main() 
{
    f(5.0);
    f(1);
    f('a');
}

Another example:

//demo2.cpp(https://coliru.stacked-crooked.com/a/7b1a94ad377ac1f6)
//Why this function template specialization compiles? 
//I think it's function partial template specialization indeed.
#include <vector>
#include <iostream> 
using namespace std;

//function template
template<typename T, class N> void compare(T num1, N num2) {
    cout << "standard function template" << endl;
    if(num1>num2)
        cout << "num1:" << num1 << " > num2:" << num2 <<endl;
    else
        cout << "num1:" << num1 << " <= num2:" << num2 << endl;
}

//function partial template specialization
template<class N> void compare(int num1, N num2) {
    cout<< "partitial specialization" <<endl;
    if (num1>num2)
        cout << "num1:" << num1 << " > num2:" << num2 << endl;
    else
        cout << "num1:" << num1 << " <= num2:" << num2 << endl;
}

int main() {
    compare<int,int>(30,31);//call compare<int,int>(int num1, int num2)
    
    compare(5,9);           //call compare<int>(int num1, int num2)

    compare(30,'1');        //call compare<char>(int num1, char num2)

}

Why this code snippet could not been compiled whereas the aforementioned two code snippets compile successfully?

#include <vector>
#include <iostream> 
using namespace std;

template <class T1, class T2>
void f(){}
    
template <class T2>
void f<int, T2>(){}  //It's function template sepcialization, isn't it? Why it could not be compiled?

int main() {}

Here are the error messages:

main.cpp:9:6: error: non-type partial specialization 'f<int, T2>' is not allowed
    9 | void f<int, T2>(){}
      |      ^~~~~~~~~~

EDITED: Thanks to eerorika for the detailed explaination.

One more question raises, how to distinguish the overloading templates and partially specialising function templates?

In other words, why template<class N> void compare(int num1, N num2) is a template overload whereas template <class T2> void f<int, T2>(){} is attempting to partially specialise a function template?

2 Answers

Is function template specialization really allowed?

Yes, but not partial specialisation.

It seems that function partcial template specialization is not allowed.Is it really correct?

If you mean partial specialisation, that is indeed not allowed for function templates.

// Why this fucntion template specialization compiles? 
// Because this is full template specialization ...?Am I right?

Yes.

//Why this fucntion template specialization compiles? 
//I think it's function partcial template specialization

No, that is not a template specialisation at all. That is a separate template. It is an overload.

Why this code snippet could not been compiled

Because it attempts to partially specialise a function template.


how to distinguish the overloading templates and partially specialising function templates?

The syntax of function specialisation is:

template<>
ReturnType template_name<template_argument_list>(parameter_list) {
//                      ^^^^^^^^^^^^^^^^^^^^^^^^

If the syntax isn't this, then it isn't a function specialisation. Notice the highlighted part that is missing from your example that isn't a specialisation. If that part is left out, this becomes a primary template definition.

Answer to my last question.

Its syntax should have looked somewhat like the below one, if it attempts to specialise a function template.

//attempt to specialise a function template
template<class N> void compare<int, N>(int num1, N num2) {
    cout<< "partitial specialization" <<endl;
    if (num1>num2)
        cout << "num1:" << num1 << " > num2:" << num2 << endl;
    else
        cout << "num1:" << num1 << " <= num2:" << num2 << endl;
}
Related