if constexpr与std::is_same_v配合匹配成员指针类型时不生效的问题
if constexpr与std::is_same_v配合匹配成员指针类型时不生效的问题
嘿,我来帮你拆解这个问题~ 你代码里的if constexpr分支完全没匹配上预期类型,核心原因是你推导的FieldType实际上是引用类型,而不是成员变量的原始值类型,这就导致std::is_same_v的判断全部不成立。
问题根源详解
当你用decltype(p->*Field)推导类型时,p->*Field是一个左值表达式(因为你通过成员指针访问对象的成员,这个结果是可修改的左值),所以decltype会推导出引用类型:
- 对于
&A::x,decltype(p->*Field)得到的是unsigned&,而非unsigned - 对于
&A::y,得到的是double&,而非double
这时候你用std::is_same_v<FieldType, unsigned>去比较,相当于拿unsigned&和unsigned比,结果当然是false,自然就走到了else分支。
修复方案
只需要在推导FieldType时,用std::remove_reference_t去掉引用修饰符,就能得到成员变量的原始值类型了。修改FieldType的定义行:
using FieldType = std::remove_reference_t<decltype(p->*Field)>;
修复后的完整代码
#include <iostream> #include <typeinfo> #include <type_traits> struct A { unsigned x = 0; double y = 0; }; template<auto Field, typename Class> void bar(Class* p) { using FieldType = std::remove_reference_t<decltype(p->*Field)>; if constexpr (std::is_same_v<FieldType, unsigned>) { p->*Field = 42; } else if constexpr (std::is_same_v<FieldType, double>) { p->*Field = 3.14; } else { std::cout << "no matching case for field type '" << typeid(FieldType).name() << "'" << std::endl; } } int main() { A a; bar<&A::x>(&a); bar<&A::y>(&a); std::cout << std::endl; std::cout << "a.x: " << a.x << std::endl; std::cout << "a.y: " << a.y << std::endl; return 0; }
运行结果
修改后代码会正确执行两个分支的赋值逻辑,输出变为:
a.x: 42 a.y: 3.14
内容来源于stack exchange
相关产品推荐
相关产品推荐

