C++如何检测类的模板成员函数是否要求两个参数为相同类型
问题原因
- 你当前实现的
func函数只用了一个模板参数DATA约束两个入参的类型,如果传入不同类型的参数会直接触发模板参数推导失败,无法通过编译。 - 你现有代码的检测逻辑是写死用两个
int类型(operator()(1,2))校验调用合法性,和实际传入的参数类型完全无关,只要两个int可以调用目标函数,检测就永远返回真,不会匹配实际调用场景的参数类型。
解决方案
你可以直接用C++17标准库提供的std::is_invocable_v来替代自定义的检测宏,它的作用就是检测指定可调用类型是否可以用给定的参数类型列表正常调用,完全匹配你的需求。
修改后可运行的完整代码如下:
#include <iostream> #include <type_traits> #include <string> using namespace std; class A{ public: template <typename T> void operator()(T data1, T data2){ cout << data1 << ' ' << data2 << endl; } }; class B{ public: // 拆分两个入参的类型定义,允许传入不同类型的参数 template <class CLASS, typename DATA1, typename DATA2> void func(CLASS &c, DATA1 data1, DATA2 data2){ // 检测当前CLASS类型是否可以用DATA1、DATA2类型的参数调用operator() if constexpr(std::is_invocable_v<CLASS, DATA1, DATA2>) { c(data1, data2); } } }; int main(){ A a; B b; b.func(a, 1, 2); // 输出:1 2 b.func(a, 1, "2"); // 检测不通过,无输出 }
原理解释
当你传入1(int类型)和"2"(const char类型)时,std::is_invocable_v<A, int, const char*>会返回false:因为类A的operator()要求两个入参是同一个模板参数类型T,int和const char无法匹配到同一个T,模板推导失败,所以if constexpr的条件不成立,不会执行调用逻辑,完全符合你预期的效果。
如果你不想用标准库提供的检测工具,也可以修改你自定义的has_member宏来适配动态参数类型:
// 修改宏定义,支持传入任意参数类型列表 #define has_member_call(T, ...) has_member_impl<T>( [](auto&& obj)->decltype(obj(std::declval<__VA_ARGS__>()...)){} ) // 在func中使用 if constexpr(has_member_call(CLASS, DATA1, DATA2)) { c(data1, data2); }
这个实现的效果和std::is_invocable_v完全一致。
内容的提问来源于stack exchange,提问作者LI.LE
相关产品推荐
相关产品推荐

