example/quick_status_code_from_enum.cpp failed to compile for gcc version <= 7
lzhangzz opened this issue · comments
when trying to compile the quick status code from enum example, I got the following error for gcc version <= 7.
<source>: In function 'constexpr system_error2::quick_status_code_from_enum_code<another_namespace::AnotherCode> another_namespace::status_code(another_namespace::AnotherCode)':
<source>:76:144: error: could not convert 'c' from 'another_namespace::AnotherCode' to 'system_error2::quick_status_code_from_enum_code<another_namespace::AnotherCode> {aka system_error2::status_code<system_error2::_quick_status_code_from_enum_domain<another_namespace::AnotherCode> >}'
constexpr inline SYSTEM_ERROR2_NAMESPACE::quick_status_code_from_enum_code<another_namespace::AnotherCode> status_code(AnotherCode c) { return c; }
^
<source>: In function 'int main(int, char**)':
<source>:84:88: in constexpr expansion of 'another_namespace::status_code(another_namespace::AnotherCode)()'
<source>:84:88: error: constexpr call flows off the end of the function
SYSTEM_ERROR2_CONSTEXPR14 auto v = status_code(another_namespace::AnotherCode::error2);
^
looks like implicit conversion from enum is not working.
Oh dear, and here I was sending you to this from ned14/outcome#254.
I can repeat your issue exactly: https://godbolt.org/z/xo9dE6EqY
As much as this is me hand waving away the problem, if you're stuck on GCC 7, I'd suggest just explicit constructing wherever GCC 7 refuses to find the implicit conversion. So, for example: https://godbolt.org/z/vfz9WTMcG
As I mentioned in the other issue, GCC 7 is still my primary dev compiler for LLFIO, and I haven't found any showstopper problems. It also does heavy complex customisation of status code, so it's not a trivial user.
I agree that constructing explicitly is sufficient as a workaround.
However, I'm curious why this is happing. And to my suprise I just find that even on GCC7 static_assert(std::is_convertible<AnotherCode, StatusCode>::value)
does not complain at all. As I recall that is_convertible is defined as the well-form-ness of To f() { return std::declval<From>(); }
.
Recent releases of compilers haven't had the QoI that older ones did. GCC 6 was quite solid compared to the many more surprises in say GCC 10, which I still can't use in production because it just doesn't work well enough. clangs up until and including 7 were also solid, since I see weird failures to emit symbols in heavy metaprogrammed code. The only compiler uncategorically better than before is MSVC.
is_convertible will be a compiler intrinsic in newer compilers, and as such can experience bugs. Recursive instantiation of constexpr possible code is a common source of trait intrinsic bugs.
Fixed!