提供方法指针和派生类型对象时,std::bind的一致性
Conformance of std::bind when providing a method pointer and an object of derived type
这个问题基本上是我给出的答案的后果。我刚刚意识到标准中的措辞似乎省略了一些情况。考虑这段代码:
#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 Requirements [function .require]
1定义INVOKE
(f, t1, t2, ..., tN)
如下:-
(t1.*f)(t2, ..., tN)
,当f
是指向T
类成员函数的指针,t1
是T
类型的对象或对T
类型对象的引用或对T
派生类型对象的引用时;-
((*t1).*f)(t2, ..., tN)
,当f
是指向类T
成员函数的指针,且t1
不是上一项中描述的类型;-
t1.*f
,当N == 1
和f
是指向类T
的成员数据的指针,t1
是T
类型的对象或对T
类型的对象的引用或对从T
派生的类型的对象的引用时;-
(*t1).*f
当N == 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)(...)
,对吗?这也是我应该关心的问题吗?还是说标准定义是从"派生"来的?在给定的上下文中?
c++ 11标准第20.8.9.1.3段以INVOKE()
伪函数的方式定义了调用std::bind()
的效果:
请注意,对返回:一个具有弱结果类型(20.8.2)的转发呼叫包装器
g
。g(u1, u2, ..., uM)
的效力为INVOKE (fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of<FD cv & (V1, V2, ..., VN)>::type)
std::forward<>
的调用将始终返回引用类型,无论是左值引用还是右值引用。根据第20.2.3/1-2段,事实上:
template <class T> constexpr T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> constexpr T&& forward(typename remove_reference<T>::type&& t) noexcept;
返回:
static_cast<T&&>(t)
因此,INVOKE
伪函数(注意:不是bind()
函数!)将在这里用引用调用,这是由您引用的定义支持的。
我相信标准本身从来没有使用INVOKE()
伪函数(这只是一些内部形式)与对象(不是对对象的引用)从T
派生的类型。
但是,这并不意味着您不能使用从T
派生的类型的对象(不是对象的引用)调用std::bind()
或其他根据INVOKE()
给出定义的函数。
- 使用 std::应用于 std::bind
- PCL:当我在setConditionFunction中使用std::bind 时,没有合适的转换函数
- std::bind on statd::array 的运算符 []
- std::bind c++ in if statement
- std::bind 是否实现了 std::ref 和 std::cref 来消除函数调用的歧义?
- C++ 事件管理器的回调,使用 std::function 和 std:bind 以及派生类作为参数
- 试图克服 std::bind 编译错误
- c++ std::bind within function
- std::bind to void* to std::function
- std::bind 和 std::函数术语不值为接受 0 个参数?
- 在调用 std::bind 的产品后意外调用析构函数
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- 我们应该在使用 std::bind 应用之前检查一个不为空的函数吗?
- 为什么 std::bind 静态类型检查传递给函数的参数?
- 对函数库中的语法感到困惑 std::bind
- 在模板类成员上使用 std::bind
- 如何将参数从函数传递给 std::bind
- 如何在C++中使用 std::bind 函数作为信号处理程序?
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- 在模板函数参数中使用 std::bind