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

C++17编译时判断shared_ptr底层类型foo方法的参数适配性

问题描述

现有如下C++17代码:

template <typename T>
using ptr_t = std::shared_ptr<const T>;

class some_type;

class A { some_type foo() const; };
class B { some_type foo() const; };
class C { some_type foo(int) const; };

std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>> var;

需要给这个std::variant编写一个visitor,在编译时判断每个shared_ptr指向的底层类型的foo方法是否能接受int参数,从而自动选择调用foo(15)还是无参的foo()。visitor框架如下:

struct visitor
{
  template <typename T>
  ptr_t<some_type> operator()(const T& config) const
  {
    if constexpr (/* 此处需编写判断逻辑 */)
        return config->foo(15);
    else
        return config->foo();
  }
};

其中模板参数T为ptr_t<A>、ptr_t<B>或ptr_t<C>类型。

解决方案

可以借助C++17的constexpr特性与标准库类型 trait,实现编译期的方法可调用性检测。核心是先提取shared_ptr的底层元素类型,再判断该类型的foo方法是否支持传入int参数。

完整的visitor实现如下:

#include <memory>
#include <variant>
#include <type_traits>

template <typename T>
using ptr_t = std::shared_ptr<const T>;

class some_type;

class A { some_type foo() const; };
class B { some_type foo() const; };
class C { some_type foo(int) const; };

struct visitor
{
    template <typename T>
    ptr_t<some_type> operator()(const T& config) const
    {
        // 提取shared_ptr指向的底层元素类型
        using ElementType = typename T::element_type;
        
        // 编译期检测:const ElementType*调用foo(int)是否合法,且返回值为some_type
        if constexpr (std::is_invocable_r_v<some_type, decltype(&ElementType::foo), const ElementType*, int>)
            return config->foo(15);
        else
            return config->foo();
    }
};

逻辑说明

  1. 提取底层类型:通过typename T::element_type获取shared_ptr包裹的原始类型(如A、B、C)。
  2. 编译期检测:
    • std::is_invocable_r_v是C++17提供的类型 trait,用于验证:以指定参数调用目标可调用对象时,是否合法且返回值可转换为指定类型。
    • 此处验证的是:ElementType的foo成员函数,在const ElementType*(对应config->的指针类型)上调用时,能否接受一个int参数,且返回值为some_type。
    • 检测结果为true时编译带参调用分支,否则编译无参调用分支。

如果可以使用C++20,还能通过更直观的requires表达式简化判断:

if constexpr (requires(const ElementType& obj) { obj.foo(15); })

内容的提问来源于stack exchange,提问作者M.K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:35:27