[英]Non-pointer function type can be a non-type parameter?
我一直在试验C ++中的函数类型。 请注意,我的意思不是指向函数的指针类型,例如:
typedef void (*voidFuncPtr)();
但更加奇特:
typedef void (voidFunc)();
我没想到会编译以下代码,但是令人惊讶的是:
template<voidFunc func>
class funcClass
{
public:
void call() { func(); };
};
void func()
{ }
void Test()
{
funcClass<func> foobar;
foobar.call();
}
但是,如果我尝试将以下内容添加到funcClass:
voidFuncPtr get() { return &func; }
我收到错误Address expression must be an lvalue or a function designator
我的第一个问题是:编译器用来假装func类型实际上是可以传递给实例的东西? 只是把它当作参考? 第二个问题是:如果它甚至可以被调用,为什么不能使用它的地址? 另外,这些非指针功能类型称为什么? 我只是因为boost :: function而发现了它们,却从未找到关于它们的任何文档。
该标准的第14.1.4节规定:
非类型模板参数应具有以下(可选,具有cv限定)类型之一:
—整数或枚举类型,
—指向对象的指针或指向函数的指针 ,[ 这就是你的 ]
—对对象的左值引用或对函数的左值引用,
—指向成员的指针,
— std :: nullptr_t。
§14.1.6说
非类型非参考模板参数是prvalue。 不得将其赋值或以任何其他方式更改其值。 非类型非引用模板参数不能采用其地址 。 当非类型非引用模板参数用作引用的初始化程序时,始终使用临时变量。
这样就可以解释您所看到的两种行为。
请注意, func
与&func
(§14.3.2.1)相同:
[非类型模板参数可以是]一个常数表达式(5.19),该常数指定具有静态存储期限和外部或内部链接的对象的地址,或者具有外部或内部链接的函数,包括函数模板和函数模板ID,但不包括非静态类成员,表示为&id-expression(忽略括号),但如果名称是指函数或数组 ,则可以省略&;如果相应的template-parameter是引用,则应省略; 要么...
因此,它只是一个函数指针。
假定代码编译时没有地址操作符和指针(包括函数和成员函数的指针)是有效的模板参数,似乎编译器认为voidFunc
是函数指针类型,即该类型的衰减版本。 在C ++ 2003和C ++ 2011之间,此规则不变。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.