复杂的 C 样式类型转换表达式的工作原理

How does a complex C style type casting expression work?

本文关键字:工作 表达式 类型转换 样式 复杂      更新时间:2023-10-16

我正在寻找一种将标准字符串大写的方法。 我找到的答案包括以下代码:

int main()
{
    // explicit cast needed to resolve ambiguity
    std::transform(myString.begin(), myString.end(), myString.begin(),
      (int(*)(int)) std::toupper)
}

有人可以解释一下铸造表达式"(int(*( (int(("吗? 我找到的所有其他转换示例和说明仅使用简单的类型转换表达式。

它实际上是一个简单的类型转换 - 但是一个函数指针类型。

std::toupper有两种口味。一个拿intint返回;另一个拿intconst locale&,返回int。在这种情况下,它是第一个需要的,但编译器通常没有任何办法知道这一点。

(int(*)(int)) 是函数指针的强制转换,该指针采用int(右侧部分(并返回int(左侧部分(。只有 toupper 的第一个版本可以这样转换,因此它消除了编译器的歧义。

(int(*((int(( 是函数指针类型的名称。该函数返回 (int(,是一个函数 *,并采用 (int( 参数。

正如其他人已经提到的,int (*)(int)指向函数的类型指针,该函数获取并返回int 。然而,这里缺少的是这个强制转换表达式的作用:与其他强制转换表达式不同,它不会真正强制转换(即它不会将值转换为不同的类型(,但它从名为std::toupper具有签名int(int)函数集中进行选择。

但是请注意,此方法有些脆弱:如果由于某种原因没有匹配函数(例如,因为不包含相应的标头(,而只有一个不匹配的函数(因此不会出现歧义(,那么这个强制转换表达式确实会变成一个强制转换,更准确地说是一个reinterpret_cast,具有不希望的效果。为了确保不会发生意外的强制转换,应使用 C++ 样式强制转换语法而不是 C 样式强制转换语法:static_cast<int(*)(int)>(std::toupper)(实际上,在这种情况下std::toupper这种情况不会发生,因为唯一的替代函数是模板化的,因此不明确,但是它可能发生在其他重载函数中(。

巧合的是,在这种情况下,新样式的强制转换语法也更具可读性。

另一种无需任何强制转换表达式即可工作的可能性如下:

int (*ptoupper)(int) = &std::toupper; // here the context provides the required type information
std::transform(myString.begin(), myString.end(), myString.begin(), ptoupper);

请注意,上下文无法提供必要的信息的原因是std::transform在最后一个参数上模板化,因此编译器无法确定要选择的正确函数。

int function(int);

获取int并返回int的函数。

int (*function_pointer)(int);

指向获取int并返回int的函数的指针。

int (*)(int)

指向获取int并返回int的函数的指针的类型。

<cctype>std::toupper已经有int (*)(int)型,但<locale>中的那个在charT上模板化,我认为这是投射的原因。 但ptr_fun会更清楚。