C++如何检测模板参数是否为指定签名的函数类型
问题根源
函数名作为实参传递给模板函数时,模板参数T会被推导为函数指针类型,而非原生函数类型。你当前的类型萃取仅匹配float(float)、float(float,float)的原生函数类型,无法匹配对应的指针类型float(*)(float)、float(*)(float,float),因此始终返回false。
解决方案
方案1:修改自定义类型萃取兼容函数指针
调整类型萃取的判断逻辑,移除指针修饰后再对比类型即可:
// 单参数float返回函数判断 template<typename T, typename = void> struct is_numeric_function1 : std::false_type {}; template<typename T> struct is_numeric_function1<T, std::enable_if_t<std::is_same_v<std::remove_pointer_t<T>, float(float)>> > : std::true_type {}; // 双参数float返回函数判断 template<typename T, typename = void> struct is_numeric_function2 : std::false_type {}; template<typename T> struct is_numeric_function2<T, std::enable_if_t<std::is_same_v<std::remove_pointer_t<T>, float(float, float)>> > : std::true_type {};
C++17及以上版本可以新增变量模板简化调用:
template<typename T> constexpr bool is_numeric_function1_v = is_numeric_function1<T>::value; template<typename T> constexpr bool is_numeric_function2_v = is_numeric_function2<T>::value;
bisect函数中直接调用即可:
constexpr bool is_function1 = is_numeric_function1_v<T>; constexpr bool is_function2 = is_numeric_function2_v<T>;
方案2:使用标准库std::is_invocable_r(推荐)
如果需要兼容lambda、std::function等更多可调用对象,直接用标准库提供的可调用对象判断逻辑更简洁通用:
#include <type_traits> template <typename T> float bisect(T value, float min, float max, float tol) { // 判断是否可传入1个float参数调用,返回值为float类型 constexpr bool is_function1 = std::is_invocable_r_v<float, T, float>; // 判断是否可传入2个float参数调用,返回值为float类型 constexpr bool is_function2 = std::is_invocable_r_v<float, T, float, float>; std::cout << is_function1 << " " << is_function2 << std::endl; // 必须使用if constexpr,避免不匹配的分支代码编译报错 if constexpr(is_function1) { // 单参数函数逻辑 } else if constexpr(is_function2) { // 双参数函数逻辑 } // 其余逻辑 }
该方案无需自定义类型萃取,兼容性更强。
内容的提问来源于stack exchange,提问作者matikowy
相关产品推荐
相关产品推荐

