I'm playing around with templates, compile-time evaluation and pointers to members.
I don't understand why the following code doesn't set a.x to 42 and a.y to 3.14. According to the output, FieldType is unsigned (printed as "j") in the A::x case, and double (printed as "d") in the A::y case. Still, the if constexpr chain doesn't match any of those cases.
#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 = 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;
}
Playground on Compiler Explorer
Output:
no matching case for field type 'j'
no matching case for field type 'd'
a.x: 0
a.y: 0
decltype(p->*Field) yields unsigned& or double&. You get expected output with
if constexpr (std::is_same_v<FieldType,unsigned&>) {
p->*Field = 42;
}
else if constexpr (std::is_same_v<FieldType, double&>) {
p->*Field = 3.14;
}
Or rather use using FieldType = std::decay_t<decltype(p->*Field)>;
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With