C++ 这两个函数签名之间有什么区别?

C++ 这两个函数签名之间有什么区别?,c++,c++11,C++,C++11,我被告知这两个签名之间的差异与左值/右值无关 #include <iostream> template <typename RET_TYPE, typename...ARGs> void takeFunction(RET_TYPE(*&& /*function*/)(ARGs...)) { std::cout << "RValue function" << std::endl; } template <typena

我被告知这两个签名之间的差异与左值/右值无关

#include <iostream>

template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(*&& /*function*/)(ARGs...))
{
    std::cout << "RValue function" << std::endl;
}

template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(*& /*function*/)(ARGs...))
{
    std::cout << "LValue function" << std::endl;
}

void function()
{
}

int main()
{
    void(*f)() = function;
    takeFunction(&function);
    takeFunction(f);
    return 0;
}
#包括
样板
空函数(返回类型(*&&/*函数*/)(参数…)
{
std::cout
RET_TYPE(*&&/*函数*/)(ARGs…
是对函数指针的右值引用

RET_TYPE(*&/*function*/)(ARGs…
是对函数指针的左值引用

&function
创建一个右值临时函数指针。因此
takeFunction(&function);
解析为
RET_类型(*&&/*function*/)(ARGs…

void(*f)(=function;
定义一个命名的左值函数指针。因此
takeFunction(f);
解析为
RET_TYPE(*&/*function*/)(ARGs…


除了这个左值/右值差异之外,这两个函数没有其他区别。

函数和函数指针之间有区别


函数之所以不同,是因为它们不是对象(在这个词的标准意义上)。没有函数右值这样的东西(除了某些涉及非静态成员函数的奇怪情况)。事实上,对函数的右值引用是左值,无论是否命名

指向函数的指针是指针,它们是对象。您可以有指向函数类型的指针的prvalue,指向函数类型的指针的xvalue,或指向函数类型的指针的左值。
&function
创建指向函数的prvalue指针;在
void(*f)()=函数;
,函数到指针的转换用于将函数左值
函数
转换为prvalue指针到函数,并使用prvalue指针初始化
f

现在考虑这组重载:

template <typename RET_TYPE, typename...ARGs>
void takeFunctionRef(RET_TYPE(&& /*function*/)(ARGs...)) // #1
{
    std::cout << "RValue function" << std::endl;
}

template <typename RET_TYPE, typename...ARGs>
void takeFunctionRef(RET_TYPE(& /*function*/)(ARGs...)) // #2
{
    std::cout << "LValue function" << std::endl;
}

takeFunctionRef(function); // calls #2
takeFunctionRef(std::move(function)); // still calls #2!
模板
void takeFunctionRef(RET_类型(&&/*函数*/)(ARGs…)/#1
{

在我看来,第一个是对函数的引用,第二个是对函数指针的引用
,这将是对函数的引用,这是一个左值?正确。而且,我似乎记得所有对函数的右值引用实际上都被解析为左值引用。换句话说,你不能真正拥有对函数的右值引用。我要找到一些对它的标准引用。所以在你指定的重载集中,只有如果两者都存在,则有一个可用(#2),但如果声明没有另一个,则可以使用其中一个?我知道这并不是很含糊,但至少它不应该生成一个警告,即永远不会调用一个?@Adrian是的,但我怀疑这种情况在实际代码中发生的频率几乎不足以证明实现警告的成本是合理的。“没有函数右值这样的东西。”-好吧,如果我们严格按照标准来讨论的话,我认为有一些函数类型的PRValue,但是它们的使用受到了非常严格的限制,以至于在实际应用中,在它们的值类别非常重要的上下文中,你根本无法遇到它们;A;
,表达式
A::f
A.f
分别是[5.1.1p9]和[5.2.5p4.3.2]规定的函数类型的PR值。