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

基于函数模板参数类型特征的Callee类SFINAE创建实现问询

问题:基于函数模板参数的类型特征选择Callee创建实现

需求概述

我希望调用create函数的不同实现,返回以函数型模板参数实例化的Callee类指针,这些实现需要根据函数型模板参数的返回值及参数的type_traits来选择。

现有代码结构

基类定义

template <typename T> class Callee;

template <typename TReturn, typename... TParams> class Callee<TReturn(TParams...)>
{
public:
    Callee() {}

    virtual TReturn call(TParams... data) = 0;
};

当前Creator实现

创建的派生对象会被注册,之后可通过标识符获取Callee<TReturn(TParams...)>*类型的指针。为简化使用,实现了CallerCreator类,其静态成员函数调用内部createInternal函数获取实例:

template <typename... TParams> class CallerCreator; 

template <typename T, bool containsRef = false> static Callee<T>* createInternal(uint32_t id)
{
    Callee<T>* callee
        = reinterpret_cast<Callee<T>*>(searchCallee(id));

    if (callee == nullptr)
    {
        callee = new OtherCallee<T, containsRef>(id);
    }
    return callee;
}

template <typename TReturn, typename... TParams>
class CallerCreator<TReturn(TParams...)> final
{
public:
    static Callee<TReturn(TParams...)>* create(uint32_t id)
    {
        return createInternal<TReturn(TParams...), contains_reference<TParams...>::value || std::is_reference<TReturn>::value>(id);
    }
};

类型特征检测实现(C++14)

基于参数包检测是否包含引用类型:

template <typename... List> struct contains_reference : std::true_type
{
};

template <typename Head, typename... Rest>
struct contains_reference<Head, Rest...>
    : std::conditional<std::is_reference<Head>::value, std::true_type, contains_reference<Rest...>>::type
{
};

template <typename Tp> struct contains_reference<Tp> : std::false_type
{
};

此外还实现了contains_non_trivially_copyable和contains_non_standard_layout。

OtherCallee实现

当未找到已注册的Callee时,会创建OtherCallee,它根据是否包含引用类型有不同特化:

template <typename T, bool containsRef = false> class OtherCallee;
template <typename TReturn, typename... TParams>
class OtherCallee<TReturn(TParams...), false> : public Callee<TReturn(TParams...)>
{
public:
    explicit OtherCallee(uint32_t id)
    {
        // static_assert(not contains_non_standard_layout<TParams...>::value, "You cannot use non-pod-types!");
        // static_assert(not contains_non_trivially_copyable<TParams...>::value, "You cannot use non-pod-types!");

        // static_assert(std::is_standard_layout<TReturn>::value, "You cannot use non-pod-types!");
        // static_assert(std::is_trivially_copyable<TReturn>::value, "You cannot use non-pod-types!");
    }
    TReturn call(TParams... data) override
    { /* 无引用时的处理逻辑 */ }
};

template <typename TReturn, typename... TParams>
class OtherCallee<TReturn(TParams...), true> : public Callee<TReturn(TParams...)>
{
public:
    explicit OtherCallee(uint32_t id)
    {
    }
    TReturn call(TParams... data) override
    { /* 含引用时的处理逻辑(如移除引用) */}
};

核心问题

我希望当OtherCallee构造函数内的static_assert条件满足时(即返回值或参数为非POD类型),createInternal函数完全不创建OtherCallee对象,直接返回searchCallee的结果,避免触发断言。

尝试过传递TReturn和TParams...做全特化,也考虑过enable_if,但不知道如何区分返回值是否为void及处理参数包。

内容的提问来源于stack exchange,提问作者NetoBF

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:24:54