函数指针和返回类型转换
function pointers and return type conversions
>假设我有一个函数执行一些副作用,然后返回一个答案:
int foo()
{
perform_some_side_effect();
return 42;
}
我想将foo
绑定到函数指针,但我对答案不感兴趣,只是副作用:
void (*bar)() = foo;
但是,这似乎是一个类型错误:
error: invalid conversion from ‘int (*)()’ to ‘void (*)()’
这个错误背后的理由是什么?为什么类型系统不允许我忽略答案?
附带说明一下,如果我将函数指针包装在std::function
中,它可以工作:
std::function<void()> baz = foo;
std::function
(显然)如何设法规避类型系统中的这种限制?
这个错误背后的理由是什么?为什么类型系统不允许我忽略答案?
原因是类型不同,调用位置(通过函数指针)生成的代码不同。考虑一个调用约定,其中所有参数都写入堆栈,并且返回值的空间也保留在堆栈中。如果调用经过void (*)()
则堆栈中不会为返回值保留空间,但函数(不知道它是如何被调用的)仍将42
写入调用方应该保留空间的位置。
std::function(显然)如何设法绕过类型系统中的这种限制?
它没有。它创建一个函数对象,用于包装对实际函数的调用。它将包含一个成员,如下所示:
void operator()() const {
foo();
}
现在,当编译器处理对foo
的调用时,它知道调用返回int
的函数必须做什么,并且它将根据调用约定执行此操作。因为模板不返回,所以它只会忽略值 - 实际返回的值。
std::function
只需要与源代码兼容 - 也就是说,它可以生成一个新类,该类生成忽略结果的新计算代码。函数指针必须与二进制兼容,并且不能执行该作业 - void(*)()
和int(*)()
指向完全相同的代码。
您可以考虑std::function<>
针对您的特定情况执行此操作:
void __func_void()
{
foo();
}
它实际上比这要复杂一些,但关键是它会生成模板代码以及类型擦除,而不关心细节。
除了其他人一直在说的内容之外,调用方还需要返回类型来知道它应该在结果上调用哪个析构函数(返回值可能是临时的)。
不幸的是,这并不像
auto (*bar)() = foo;
尽管海湾合作委员会和Clang接受这一点。我需要重新检查规范以查看这是否真的正确。
更新:规范说
auto 类型说明符表示要声明的变量的类型应从其初始值设定项中推导出来,或者函数声明符应包含尾随返回类型。
这在快速阅读时可能会产生误导,但这由 GCC 和 clang 实现,仅适用于顶级声明符。在我们的例子中,这是一个指针声明符。嵌套在其中的声明符是一个函数声明符。因此,只需用auto
代替void
,编译器就会为您推断出类型。
顺便说一句,您始终可以手动完成此操作,但是要使其工作需要一些技巧
template<typename FunctionType>
struct Params;
template<typename ...Params>
struct Params<void(Params...)> {
template<typename T>
using Identity = T;
template<typename R>
static Identity<R(Params...)> *get(R f(Params...)) {
return f;
}
};
// now it's easy
auto bar = Params<void()>::get(foo);
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 类型转换问题:返回为整数而不是浮点/类型
- 如何将两个 jlong 数据类型转换为 jstring,然后将两个字符串连接在一起以便从 JNI 将字符串返回给 jav
- 是否可以将一种函数类型转换为另一种采用相同参数但返回类型不同的函数类型
- 使用类型转换在 C++ 中返回 2D 数组
- 我的程序返回整数值,但即使在显式类型转换之后也应该给出双值
- clang,返回带有类型转换的std::unique_ptr
- 协变返回类型和类型转换
- 函数指针和返回类型转换
- 为什么我们需要从基类型转换为派生类型并返回
- 'decltype':函数返回类型"T"转换为用户定义类型的"T&"(VS2010)
- 从带有shared_ptr的函数返回时进行类型转换
- 静态强制转换返回类型
- 可以安全地将预先存在的类型转换NULL的返回与较新的nullptr进行比较吗
- 将函数的返回值类型转换为大小相同的不相关类型
- 在返回中C++类型转换优先级
- C++将派生类强制转换为基类型并返回派生类
- 对模板函数的返回值进行类型转换