复杂的C样式类型转换表达式如何工作?

时间:2011-11-29 15:54:06

标签: c++ casting

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

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

有人能解释一下铸造表达式“(int(*)(int))”吗?我发现的所有其他演员示例和描述都只使用简单的类型转换表达式。

4 个答案:

答案 0 :(得分:5)

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

std::toupper有两种风格。一个人需要int并返回int;另一个需要intconst locale&并返回int。在这种情况下,它是第一个需要的,但编译器通常无法知道这一点。

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

int function(int);

一个功能int并返回int

int (*function_pointer)(int);

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

int (*)(int)

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

来自std::toupper

<cctype>已经有int (*)(int)类型,但<locale>中的charT中的{{1}}被模板化,我认为这是投票的原因。但ptr_fun会更清楚。

答案 3 :(得分:2)

正如其他人已经提到的,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是最后一个参数的模板,因此编译器无法确定要选择的正确函数。