【发布时间】:2018-05-15 19:00:06
【问题描述】:
不同类型的函数指针不能直接比较:
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
// Doesn't compile, the comparison is not allowed
std::cout << std::boolalpha << (&foo == &bar) << std::endl;
return 0;
}
但是,如果一个函数指针被强制转换为另一个函数指针的类型,是否定义了将该强制转换的结果与另一个函数指针进行比较的行为?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
auto cast_ptr = reinterpret_cast<decltype(&bar)>(&foo);
// Printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_ptr == &bar) << std::endl;
}
如果两个运算符都被转换为一个共同但不同的类型呢?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
using cast_type = void(*)();
auto cast_foo = reinterpret_cast<cast_type>(&foo);
auto cast_bar = reinterpret_cast<cast_type>(&bar);
// Also printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_foo == cast_bar) << std::endl;
}
我知道函数指针比较相等当且仅当它们都指向nullptr 或同一个函数。我不清楚的是,是否允许在比较中使用已转换为另一个函数指针类型的函数指针。
上下文
我正在维护一个带有 c 兼容 API 的 c++ 库。该库记录对 API 函数的每次调用。在运行时有选择地禁用某些功能的日志记录变得很有用。就可用性而言,当前最好的提议是提供一个新的 API 函数,该函数将指向应该禁止记录的 API 函数的指针作为参数。由于 API 函数具有不同的参数,因此这些指针将具有不同的类型,并且需要转换为常见的函数指针类型,例如 void(*)()。然后,在记录 API 函数调用之前,将在 void(*)() 的容器中搜索被调用函数的地址,以了解是否记录该调用。
【问题讨论】:
-
投射到
std::intptr_t怎么样? -
@PasserBy 这是一个有趣的想法。
std::intptr_t可以存储指针,但我不清楚它是否可以存储函数指针。函数指针不需要与常规指针具有相同的大小。 -
指针可以显式转换为任何大到足以容纳它的整数类型。映射函数是实现定义的。 如果大小足够大,似乎(大多数情况下)它很好。
-
除了将“指向
T1的指针”类型的纯右值转换为“指向T2的指针”类型(其中T1和T2是函数类型)并返回对其原始类型产生原始指针值,这种指针转换的结果是未指定的。 似乎转换为不同的函数指针类型并使用它们是不可靠的 -
而不是依赖于实现定义的行为,你不能只存储类型擦除的包装器和正确定义的 operator== 吗?
标签: c++ casting function-pointers