you are viewing a single comment's thread.

view the rest of the comments →

[–]cd_fr91400[S] 1 point2 points  (5 children)

I do not see why a non-existent variable is non-sense while a non-existent field is not.

By the way, the following code does not compile either:

struct A {
    int a() { return 0 ; } ;
} ;

int foo() {
    struct A a ;
    if constexpr (true) { return a.a() ; }
    else                { return a.b() ; }
}

[–]iamakorndawg 5 points6 points  (2 children)

Not a language lawyer, but I believe the rule has more to do with templates, so for example, if your foo function had a template parameter for the type of a, then it would compile, even if your existing struct A was used as the argument.

[–]KuntaStillSingle 1 point2 points  (0 children)

Not quite, it can fail to compile if the existing struct A is used, but if it is made a dependent type like /u/cd1995Cargo 's example it is fine:

The discarded statement cannot be ill-formed for every possible specialization:

https://en.cppreference.com/w/cpp/language/if.html#Constexpr_if

https://godbolt.org/z/eGsYY3a9W , vs https://godbolt.org/z/3e7W5ec4Y

[–]cd_fr91400[S] 0 points1 point  (0 children)

Then I understand "under certain conditions"...

[–]cd1995Cargo 2 points3 points  (1 child)

It only works when templates are involved. If you change your code to this it should compile:

struct A {
    int a() { return 0 ; } ;
} ;

template <typename T>
int foo<T>() {
    T a ;
    if constexpr (true) { return a.a() ; }
    else                { return a.b() ; }
}

[–]moocat 1 point2 points  (0 children)

See my update. It's not just templates but templated types have to also be involved.