这个问题基本上是我给出的这个答案的后果。我刚刚意识到标准中的措辞似乎省略了一些情况。考虑这段代码:
#include <iostream>
#include <functional>
struct foo
{
void f(int v) { std::cout << v << std::endl; }
};
struct bar : foo {};
int main()
{
bar obj;
std::bind(&foo::f, obj, 1)();
}
该标准在 20.8.9.1.2 中描述了std::bind
调用它时的效果和发生的情况。它转发到20.8.2,相关部分是:
20.8.2 要求 [func.require]
1按如下方式定义INVOKE :
(f, t1, t2, ..., tN)
—
(t1.*f)(t2, ..., tN)
whenf
是指向类的成员函数的指针,T
并且t1
是类型对象T
或对类型对象的T
引用或对派生于的类型对象的引用T
;—
((*t1).*f)(t2, ..., tN)
whenf
是指向类的成员函数的指针,T
并且t1
不是上一项中描述的类型之一;—
t1.*f
当N == 1
andf
是指向类的成员数据的指针T
并且t1
是类型对象T
或对类型对象的T
引用或对派生于的类型对象的引用时T
;—
(*t1).*f
whenN == 1
和f
是指向类的成员数据的指针,T
并且t1
不是上一项中描述的类型之一;—
f(t1, t2, ..., tN)
在所有其他情况下。
读到这里,第一个列表项似乎允许三种情况:
t1
是类型的对象T
- 或对类型对象的引用
T
- 或对派生自的类型的对象的引用
T
但在我的例子中,两者都不是。它是派生自 的类型T
,但没有引用。上面列出的情况不应该是:
t1
是类型的对象T
- 或派生自的类型的对象
T
- 或对类型对象的引用
T
- 或对派生自的类型的对象的引用
T
当然,这同样适用于 20.8.2 中的第三个列表项。
问题 1:由于 GCC 和 Clang 都接受我的代码,我想知道这是否是违反标准的缺陷报告,或者我只是读错了。
问题 2:使用多重/虚拟继承,即使一个类型派生自T
,也可能无法简单地调用(t1.*f)(...)
它,对吗?这也是我应该关注的事情,还是标准在给定的上下文中清楚地定义了“源自”?