You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取类方法返回的std::shared_ptr的element_type的现代C++解决方案

获取类方法返回的std::shared_ptr的element_type的现代C++解决方案

嗨,我来帮你搞定这个问题!你遇到的问题主要有两个关键点:一是std::result_of的使用细节没处理好,二是它在C20已经被弃用了,咱们用现代C的标准工具来解决会更顺畅。

先说说你当前代码里的问题:你写decltype(result)::element_type是错误的,因为result本身就是一个类型别名,而decltype()是用来获取表达式的类型的——你直接写result::element_type就够了,但这里还有个小坑:result是const std::shared_ptr<A>&(引用类型),引用本身没有element_type成员,得先把引用和顶层const去掉,才能拿到底层的std::shared_ptr<A>类型。

下面给你两种现代C的解决方案,覆盖C17及以上版本:

方案一:用std::invoke_result_t(替代弃用的std::result_of)

std::invoke_result_t是C++17引入的,专门用来推导可调用对象的返回类型,完美替代std::result_of。代码示例如下:

#include <memory>
#include <type_traits>

class A {};

class B {
public: // 注意:成员函数要设为public,否则外部无法获取方法指针
    const std::shared_ptr<A> foo() const;
};

// 推导B::foo的返回类型
using MethodReturnType = std::invoke_result_t<decltype(&B::foo), const B&>;
// 去掉返回类型的引用和顶层const,拿到纯净的std::shared_ptr<A>
using UnderlyingPtrType = std::remove_cv_t<std::remove_reference_t<MethodReturnType>>;
// 提取element_type,这就是你要的A类型
using ElementType = UnderlyingPtrType::element_type;

解释一下:

  • std::invoke_result_t<Callable, Args...>会模拟调用Callable并传入Args参数,返回对应的结果类型。这里因为foo是const成员函数,所以要传const B&作为实例参数。
  • std::remove_reference_t用来去掉返回类型的引用,std::remove_cv_t去掉顶层的const/volatile,这样就得到了std::shared_ptr<A>类型,自然就能访问它的element_type了。

方案二:直接用decltype+std::declval推导返回类型

这种方式更直观,不需要借助成员函数指针,直接模拟调用成员函数来获取返回类型:

#include <memory>
#include <type_traits>

class A {};

class B {
public:
    const std::shared_ptr<A> foo() const;
};

// 用std::declval创建一个const B的"虚拟实例",调用foo后用decltype获取返回类型
using MethodReturnType = decltype(std::declval<const B>().foo());
// 同样去掉引用和顶层const
using UnderlyingPtrType = std::remove_cv_t<std::remove_reference_t<MethodReturnType>>;
using ElementType = UnderlyingPtrType::element_type;

解释:

  • std::declval<T>()可以在不需要真正实例化T的情况下,生成一个T类型的右值引用,刚好用来模拟调用成员函数,非常适合推导返回类型。

额外简化(C++20及以上)

如果你的编译器支持C++20,可以用std::unwrap_reference_t简化去掉引用的步骤,或者直接用std::decay_t一次性处理引用和const:

// 用unwrap_reference_t替代remove_reference_t
using UnderlyingPtrType = std::remove_cv_t<std::unwrap_reference_t<MethodReturnType>>;

// 或者用decay_t一步到位(会同时处理引用、const、volatile,以及数组/函数转指针)
using UnderlyingPtrType = std::decay_t<MethodReturnType>;

最后再提一句:你之前用std::result_of<decltype(method)(B)>::type得到引用类型,是因为调用成员函数指针时,传入的B对象会被绑定到引用参数,所以返回类型是引用。只要调整参数为const B&,或者后续去掉引用,就能正确拿到shared_ptr类型啦。

备注:内容来源于stack exchange,提问作者Foaly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 09:39:39