真的允许函数模板特化吗?

问题描述

根据this article,它说(强调我的):

部分模板特化允许我们特化类(但 不是个别功能!)

似乎不允许函数部分模板特化。真的是这样吗?

让我困惑的是为什么这些代码片段可以成功编译:

//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');
}

一个例子:

//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)

}

为什么 this code snippet 无法编译,而上述两个代码片段编译成功?

#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() {}

以下是错误信息:

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

已编辑: 感谢 eerorika 的详细解释。

还有一个问题,如何区分重载模板和部分专门化的函数模板?

换句话说,为什么 template<class N> void compare(int num1,N num2) 是模板重载 template <class T2> void f<int,T2>(){} 试图部分特化一个函数模板?

解决方法

真的允许函数模板特化吗?

是的,但不是部分专业化。

好像不允许函数部分模板特化,真的对吗?

如果您的意思是部分专门化,那确实不允许用于函数模板。

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

是的。

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

不,这根本不是模板特化。那是一个单独的模板。这是一个过载。

为什么无法编译此代码片段

因为它试图部分特化一个函数模板。


如何区分重载模板和部分特化函数模板?

函数特化的语法是:

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

如果语法不是这个,那么它就不是函数特化。请注意您的示例中缺少的突出显示部分不是专业化。如果该部分被省略,这将成为主要模板定义。

,

回答我的最后一个问题。

如果它试图专门化一个函数模板,它的语法应该看起来有点像下面的。

//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;
}