Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: `if constexpr` and `std::is_same_v` not working

Tags:

c++

templates

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
like image 370
md2perpe Avatar asked Nov 16 '25 09:11

md2perpe


1 Answers

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

like image 129
463035818_is_not_a_number Avatar answered Nov 17 '25 23:11

463035818_is_not_a_number



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!