当static_cast后面跟着两对括号时,它的意思是什么?

21

这里说的是什么:

return static_cast<Hasher &>(*this)(key);

我无法确定*this还是key被传递给static_cast。我查看了一些资料,发现这个答案,但与我遇到的问题不同,第一对括号中没有任何内容。


8
你所缺失的关键是Hasher类有一个重载的"函数调用运算符",可以像函数一样使用。 - molbdnilo
你说得对,你链接的问题有一个显著的区别:它创建了一个类类型的临时对象,而不是在现有对象上使用 static_cast。(那里的答案解释了为什么使用空括号 (),而这是 static_cast<>() 的事实解释了为什么第一个括号不为空。)但在两种情况下,都会调用所得到的对象的 operator( something ) - Peter Cordes
1
如果您对计算顺序不确定,请添加额外的括号以消除歧义。 - Henri Menke
1
@HenriMenke 如果他们不知道求值的顺序,他们怎么知道在哪里放括号呢? - Chris H
@ChrisH 你不需要这样做。但是当编译器只接受一种替代方案时,你可能会有好运。 - Micha Wiedenmann
2个回答

33

该语句被解析为

return (static_cast<Hasher &>(*this))(key);

因此,static_cast 的参数是 *this。然后将强制类型转换的结果,称为 x,用作后缀表达式,在函数调用中使用 key 作为参数,即 x(key),其结果被返回。


7

我无法确定*this还是key被传递给static_cast

如果不确定,您可以查找语法。

在非正式文档中,static_cast的唯一可用语法是:

static_cast < new-type > ( expression )

在任何你比较的标准草案中都是如此。

因此,不存在static_cast<T>(X)(Y)语法,唯一可能的解释是:

  • new-type = Hasher&
  • expression = *this

整个语句相当于

Hasher& __tmp = static_cast<Hasher &>(*this);
return __tmp(key);

在您提供的skarupke/flat_hash_map代码中,解释是这个类从私有基类Hasher继承了一个函数调用运算符,并且它想要显式地调用那个explicitly - 也就是说,Hasher::operator()而不是任何其他继承的operator()。您会注意到相同的机制被用于显式调用其他私有继承的函数调用运算符。
如果每个策略类型参数都使用不同的函数名称,那么它将更易读,但例如您不能直接为Equal参数使用std::equal_to
如果它使用数据成员而不是私有继承来实现HasherEqual等,则可能更易读,但选择这种方式是为了允许无状态策略的empty base-class optimization

我跟随问题中的链接 skarupke/flat_hash_map 并解释了如何理解该代码。我知道通常引用行的其他可能解释。已经澄清了区别。 - Useless
我的意思是,你应该提到更广泛的显式转换情况,而不是可能是实际情况的继承特例。否则,你的回答整体上非常描述性。 - Red.Wave
我的意思是,这不会影响强制类型转换的解析方式,这也是最初的问题。我只是描述了解释来帮助OP理解他们正在阅读的代码的上下文,我不想写一篇关于执行强制类型转换的各种不同方式的文章。 - Useless
我没有看到任何与继承相关的上下文。如果您能向我展示问题的上下文中在哪里找到向上转型,我会很高兴。如果它是一个向上转型,那么指针强制转换将恰好完成作业((*static_cast<Hasher*>(this))();)。使用引用转换的事实指向更通用的显式可转换性情况。 - Red.Wave
让我们在聊天中继续这个讨论 - Useless
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接