指向函数的指针vs作为模板非类型形参的函数

Pointer to function vs function as template non-type parameter

本文关键字:函数 类型 形参 指针 vs      更新时间:2023-10-16

我试图理解下面代码片段中发生了什么:

// using FUN = void(*)(void);
using FUN = void(void);
template<FUN fun> struct Fun{};
int main ()
{
    FUN fun;
    Fun<fun>{};
}

我可以使用void(void)作为函数的非类型参数,一切正常,程序编译。但是,将类型更改为指向函数的指针,即删除第一行的注释并注释第二行,会导致错误

(g++)错误:'fun'的值不能用于常量表达式

(clang)错误:'FUN'类型的非类型模板参数(也称为'void (*)()')不是常量表达式

到底是怎么回事?函数类型实际上与指向函数的指针相同(即,无处不在地隐式转换?)我知道函数的指针不应该工作,因为FUN fun;main它不是一个常量表达式,但为什么声明FUN作为void(void);使它工作?

将类型为"array of T"或"function returning T"的非类型模板参数调整为type"指向T的指针"或"指向返回T的函数的指针"

([temp。(c++中的参数)

因此,模板Fun是同一个模板,无论FUN是声明为函数类型还是指向函数类型的指针。

但是,这个块声明:

FUN fun;

有不同的含义取决于FUN是什么。如果FUN是一个函数,则这是一个函数的块声明(如果使用odr,则必须在其他地方定义)。一般来说,可以使用函数名作为指向函数的指针类型的模板形参的实参——这里没有问题。但是如果FUN是一个函数指针,这将创建一个未初始化的函数指针。因为它是一个非const对象,所以它不能用作模板参数,就像int变量不能用作int模板参数的模板参数一样,但const int变量可以。