Is the following code a correct use of constexpr functions? It essentially tries to access the static constexpr member variable _size in various ways.
It compiles without issue using g++, but fails with msvc-2017 / 2019 and clang.
Code sample available for testing via godbolt here.
It seems that this can be made to compile (everywhere) if the constexpr function is replaced by an equivalent macro-workaround. Uncomment USE_MACRO_WORKAROUND to test.
For me, this seems to suggest a compiler bug relating to constexpr functions?
(Since the macro-version works, this suggests the compiler should have enough compile-time information available to deal with the constexpr function. Obviously g++ can do this...)
(This example is just a simple contrivance. The real code is part of this library).
#include <cstddef>
//define USE_MACRO_WORKAROUND
template <size_t N = +1>
struct expansion
{
size_t static constexpr _size = N ;
double _xdat [ N ] ;
};
#if defined(USE_MACRO_WORKAROUND)
// ugly macro-based hack that's equiv. to compile
// time foo()...
// does compile everywhere
#define foo(_aa, _bb) _aa._size + _bb._size
#else
// why does this cause problems? works for g++ 7,
// 8, 9, but not msvc, etc
template <size_t NA, size_t NB>
inline size_t constexpr foo (
expansion <NA> const& _aa,
expansion <NB> const& _bb
)
{
return _aa._size + _bb._size;
}
#endif //USE_MACRO_WORKAROUND
template <size_t NA, size_t NB>
inline void goo (
expansion <NA> const& _xx,
expansion <NB> const& _yy
)
{ // this will not compile with msvc, reporting
// C2131: expression did not evaluate to a constant
expansion<foo(_xx, _yy)> _tt;
}
int main ()
{
expansion< 2 > _x2;
expansion< 4 > _x4;
// this seems to work for both g++ and msvc
expansion<foo(_x2, _x4)> _x6;
// via msvc, this leads to the errors above
goo (_x2, _x4) ;
return 0;
}