如何编写类型特性以检查函数能否针对给定类型编译?
如何编写类型特性以检查函数能否针对给定类型编译?
嘿,刚好我对这个问题熟得很!你提到了两个自定义类型CustomNotCompatibleWithRun、CustomCompatibleWithRun,还有一个run()函数(不过你贴的代码有点不完整,我先把它补全再讲哈)。咱们的目标就是写个类型特性,判断某个类型能不能和run()一起编译对吧?
首先先把代码补全成可测试的样子,假设你的run()函数需要类型支持operator+操作:
#include <iostream> #include <type_traits> template <typename T_> struct CustomNotCompatibleWithRun { using T = T_; }; template <typename T_> struct CustomCompatibleWithRun { using T = T_; CustomCompatibleWithRun operator+(const CustomCompatibleWithRun& other) { CustomCompatibleWithRun res; // 简单实现,模拟合并操作 return res; } }; // 假设run函数需要参数支持+操作,不支持的话编译失败 template <typename T> void run(const T& obj) { auto temp = obj + obj; std::cout << "Run succeeded!" << std::endl; }
接下来咱们用C++的**SFINAE(替换失败不是错误)**特性来实现类型检查,这是这类问题的标准解法:
第一步:定义基础的类型特性模板
先写一个默认返回false的模板,当类型不兼容时就用这个版本:
template <typename T, typename = void> struct is_compatible_with_run : std::false_type {};
第二步:用SFINAE特化兼容的情况
我们需要判断run(std::declval<T>())这个表达式能不能合法编译。这里用到std::void_t来统一表达式的类型,只要表达式合法,这个特化版本就会被选中,返回true:
template <typename T> struct is_compatible_with_run<T, std::void_t<decltype(run(std::declval<T>()))>> : std::true_type {};
这里解释几个关键点:
std::declval<T>():用来生成一个T类型的右值引用,不需要构造对象就能测试表达式的合法性,特别适合测试那些没有默认构造函数的类型。std::void_t:不管括号里的表达式是什么类型,它都会转换成void,只要表达式能编译通过,这个特化模板就会被匹配。
第三步:写个辅助变量模板(可选,但更方便使用)
为了不用每次都写::value,可以定义一个变量模板:
template <typename T> constexpr bool is_compatible_with_run_v = is_compatible_with_run<T>::value;
测试一下效果
现在写个main函数验证:
int main() { std::cout << std::boolalpha; // 让cout输出true/false而不是1/0 std::cout << "CustomNotCompatibleWithRun<int>: " << is_compatible_with_run_v<CustomNotCompatibleWithRun<int>> << std::endl; // 输出false std::cout << "CustomCompatibleWithRun<int>: " << is_compatible_with_run_v<CustomCompatibleWithRun<int>> << std::endl; // 输出true return 0; }
运行后你会看到,不兼容的类型返回false,兼容的返回true,完美符合预期!
如果你的run()函数有其他要求(比如需要类型有某个成员函数do_work()),只需要修改decltype里的表达式就行,比如改成:
template <typename T> struct is_compatible_with_run<T, std::void_t<decltype(std::declval<T>().do_work())>> : std::true_type {};
备注:内容来源于stack exchange,提问作者zhanginou
相关产品推荐
相关产品推荐

