基于函数模板参数类型特征的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
相关产品推荐
相关产品推荐

