C++20下如何在模板函数中检测类实例是否包含指定成员?
问题:C++20模板函数中检测类成员的编译错误解决
我尝试在C++20的模板函数里用traits和模板特化检测类实例是否包含指定成员,定义了point2D和point3D两个结构体,以及判断是否含z成员的has_z trait。但取消print函数中判断并输出obj.z的代码注释后,编译point2D实例时会报错,提示point2D无z成员,求能解决该问题的最小修改方案及原因。
原尝试代码
#include <iostream> #include <type_traits> struct point2D { double x = 0.; double y = 0.; }; struct point3D { double x = 0.; double y = 0.; double z = 0.; }; template <typename T> struct has_z : std::false_type {}; // 默认情况 template <> struct has_z<point3D> : std::true_type {}; // 特化情况 template<typename T> void print(T const & obj) { std::cout << obj.x << " " << obj.y; //if (has_z<T>::value) std::cout << obj.z; std::cout << std::endl; }; int main() { point2D pt2D; print(pt2D); point3D pt3D; print(pt3D); }
编译运行结果:
>> g++ -o main main.cpp >> ./main 0 0 0 0
取消注释后的报错信息
>> g++ -o main main.cpp main.cpp: In instantiation of ‘void print(const T&) [with T = point2D]’: main.cpp:27:8: required from here main.cpp:21:41: error: ‘const struct point2D’ has no member named ‘z’ 21 | if (has_z<T>::value) std::cout << obj.z; | ~~~~^
最小修改方案及原因
最小修改方案
把普通if替换为C++17引入的if constexpr:
if constexpr (has_z<T>::value) std::cout << " " << obj.z;
修改后的print函数:
template<typename T> void print(T const & obj) { std::cout << obj.x << " " << obj.y; if constexpr (has_z<T>::value) std::cout << " " << obj.z; std::cout << std::endl; };
原因解释
- 普通
if是运行时分支,模板实例化时会检查分支内所有代码的合法性,哪怕该分支永远不会执行。当T=point2D时,obj.z的代码会被编译器检查,而point2D没有z成员,直接触发编译错误。 if constexpr是编译时分支,编译器会根据编译期常量条件(这里has_z<T>::value是编译期已知值),仅保留符合条件的分支代码。当T=point2D时,has_z<T>::value为false,包含obj.z的分支会被编译器完全丢弃,不会进行语法检查,自然不会报错。
内容的提问来源于stack exchange,提问作者fghoussen
相关产品推荐
相关产品推荐

