为什么C ++可以从左侧推导出赋值运算符右侧的模板参数?

时间:2017-12-22 10:03:50

标签: c++ templates language-lawyer

template <typename T>
void func(T&){
}

int main(){
    void (*p)(int&) = func;//or &func
    return 0;
}

我想知道为什么这段代码会编译(使用g ++)。似乎模板函数的论证是从p的类型推导出来的?这是标准行为吗?

编辑: 我想出了一个可能的解释。该任务有签名:

void(*&)(int&)operator=(void(*)(int&));

因此func实际上是从operator =的输入参数类型推导出来的,而不是直接从 p 的类型推导出来的。这是对的吗?

1 个答案:

答案 0 :(得分:29)

  

这是标准行为吗?

是的。当您获取函数模板的地址时(例如,在分配或初始化函数指针时执行),也会发生模板参数推导。它在[temp.deduct.funcaddr]/1中明确允许:

  

模板参数可以从拍摄时指定的类型推断出来   重载函数的地址。功能模板   函数类型和指定的类型用作P和A的类型,   扣除按照[temp.deduct.type]中的描述完成。

函数指针类型提供了上一段中的参数(A)。

  

因此func实际上是从operator =的输入参数类型推导出来的,而不是直接从p的类型推导出来的。这是对的吗?

不是真的。首先,它不是赋值,它是你正在进行的初始化。即使它使用了重载的operator=函数,你也需要推导来初始化赋值运算符的参数,这会让你回到原点。