Lambda表达式、共享指针和此类型
Lambda expression, shared pointer and the type of this
考虑以下代码:
#include <memory>
#include <cassert>
struct S: std::enable_shared_from_this<S> {
protected:
S() = default;
int bar() { return 42; }
};
struct T: S {
static std::shared_ptr<T> create() {
return std::shared_ptr<T>(new T{});
}
auto foo() {
auto ptr = std::static_pointer_cast<T>(shared_from_this());
return [ptr](){ return ptr->bar(); };
}
private:
T() = default;
};
int main() {
std::shared_ptr<T> ptr = T::create();
auto lambda = ptr->foo();
assert(lambda() == 42);
}
上面的代码编译完成。如果方法foo
修改如下,则不会:
auto foo() {
// In this case, there is no explicit cast
// The type of ptr is no longer std::shared_ptr<T>
// It is std::shared_ptr<S> instead
auto ptr = shared_from_this();
return [ptr](){ return ptr->bar(); };
}
在这种情况下,代码不再编译(既不使用GCC也不使用clang)。
显然,它将在强制转换后编译(这就是我在第一个示例中所做的),但我希望bar
即使在这种情况下也对lambda可见,因为它在其上下文中也是可访问的,也是S
接口的一部分。
我怀疑这是由于5.1.5p8,特别是:
lambda表达式的复合语句生成函数调用运算符的函数体[…],但对于[…](确定this[…]的类型和值),复合语句在lambda表达式上下文中被考虑。
事实上,clang返回的错误非常清楚:
main.cpp:8:9:注意:只能访问
T
类型对象上的此成员
我的推论正确吗
是否是由于上述段落,从而导致this
指针的确定类型与共享指针的类型不匹配的问题?
shared_ptr
参与游戏的事实让我有点难以理解
老实说,我希望这两个例子都能编译,否则两个都会失败。
看起来您只是违反了受保护访问的基本规则。也就是说,整件事与lambdas或共享指针无关。自古以来就存在的受保护访问的古老规则说,基类的受保护成员只能通过派生类的对象访问。与您上面所说的相反,在您的上下文中,S
的受保护成员不能通过S
类型的对象访问,但可以通过T
类型的对象进行访问。
整个事情可以减少以下简单的例子
struct S
{
protected:
int i;
};
struct T : S
{
void foo()
{
this->i = 5; // OK, access through `T`
T t;
t.i = 5; // OK, access through `T`
S s;
s.i = 5; // ERROR: access through `S`, inaccessible
S *ps = this;
ps->i = 5; // ERROR: access through `S`, inaccessible
}
};
我认为问题中的评论已经给出了答案,我不想在这里申请学分。
我想您可能对一种"更好"的方式感兴趣,这种方式可以执行静态强制转换的工作,而无需实际调用静态强制转换,甚至不需要知道基类:
首先定义这个有用的免费函数:
template<class T>
auto shared_from_that(T* p)
{
return std::shared_ptr<T>(p->shared_from_this(), p);
}
然后获得正确键入的共享指针:
auto foo() {
return [ptr = shared_from_that(this)](){
return ptr->bar();
};
}
简介:
调用std::shared_ptr
的2参数构造函数(似乎广泛未知),该构造函数使用arg1中shared_ptr的控制块和arg2中指向受控对象的指针。
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 如何访问在 c++ 中在类内声明的结构类型指针变量?
- (C )找到基本类型指针的儿童类型
- 表达式必须具有指向对象的指针类型(指针向量)
- 将子项复制构造到父类型指针中
- C 返回类型指针声明
- 调用虚拟函数而不通过类类型指针创建任何对象
- C++ 如何使用类类型指针制作向量
- 为什么基类型指针不能获取派生类对象的地址值?
- 如何在 C++ 中获取映射类型指针,映射
- 如何检查该类型的类型指针是正确对齐的
- 正在转换为短类型指针
- 指向任意类方法的模板非类型指针
- 如何通过强制转换类型指针将字符数组转换为uint16_t
- 指向shared_ptr的不透明类型 C 指针
- C++:从值类型指针强制转换为包含迭代器
- C/C++:访问给定类型指针的位置与访问另一类型指针的相同位置不同
- 比较类型指针
- 数据类型指针使用*(Datatype *)
- 如何打印c++中char类型指针的所有值