expanded constexpr support in Ogre::Vector#3607
expanded constexpr support in Ogre::Vector#3607ribbon-otter wants to merge 2 commits intoOGRECave:masterfrom
Conversation
It adds support for constexpr indexing into vectors and comparing them with ==, !=, <, and > on C++20 versions and above.
|
oh, if we choose to keep the test file and the testing script, what do you think would be the appropriate copyright header to include at the top? |
| OGRE_CPP20_CONSTEXPR T operator[](size_t i) const | ||
| { | ||
| assert(i < dims); | ||
| return ptr()[i]; |
There was a problem hiding this comment.
wouldnt making ptr() constexpr work too?
There was a problem hiding this comment.
perhaps I didn't do the correct combination when I tried, but that was my first strategy, and I didn't have success with it. Presumably because constexpr is a safe context where you can't do UB (to my knowledge). This is why I had to change
constexpr VectorBase(Real _x, Real _y, Real _z) : x(_x), y(_y), z(_z) {}
to
constexpr VectorBase(Real _x, Real _y, Real _z) : data{_x, _y, _z} {}
Since in a constexpr context, the for-loops would refuse access members of a union from the non-initialized path otherwise.
| Real x, y, z; | ||
| constexpr VectorBase(Real _x, Real _y, Real _z) : data{_x, _y, _z} {} | ||
| union { | ||
| struct { Real x, y, z; }; |
There was a problem hiding this comment.
anonymous structs are non-standard c++
There was a problem hiding this comment.
ah, good catch; that explains why I learned about them from reading a difference open-source game engine's source code rather than from reading Cpp reference.
you are correct, that doing pointer math on Vector is UB too. However as it is what we are currently doing, I would rather continue with that instead of doing other UB stuff.
if code is not executed, you can assume it is broken. I would rather have a gtest guarded behind "#if CPP20" and switch our custombuild to CPP20 for that, so it is actually executed. The rest looks good to me. |
|
I suppose using gtest works. I didn't use that because the error would show up at compile time (since doing the calculation at compile time is the feature; and |
|
I think I will try make a second attempt at this idea using |
|
another angle would be to fix it in operator[] like: // In VectorBase<3, Real>
Real& operator[](size_t i) {
assert(i < 3);
switch(i) {
default:
case 0: return x;
case 1: return y;
case 2: return z;
}
} |
|
That would work but my concern is performance degradation, since it compiles to code with branches or at least individually checking each case. I am leaning towards thinking that constexpr on Vector isn't possible without writing a separate implementation of Vector for c++20 compilers, or with the non-standard anonymous struct and union solution I proposed above. (though anonymous structs appear to be supported on gcc, clang, and msvc, so it is possible that using them won't cause problems in practice). |
This initial version adds support for
constexprindexing into vectors and comparing them with==,!=,<, and>on C++20 versions and above. My goal is to add support for Ogre::Vector math in aconstexprcontext as much as is possible.Because I wanted to try compiling code in a
constexprcontext with various versions of C++, I created theCppVersionTestingfolder and along with a shell script to automatically check the validity the code on each version of C++ between 14 and 23 inclusive. The script currently onlyg++(and likelyclang++). How do you feel about the script and testing file? do you want it rewritten in Cmake (I tried at first but it seemed not easy) or perhaps excluded from the project all together?Strictly speaking the code works without the OGRE_CPP20_CONSTEXPR macro to remove
constexprfor C++ versions less than c++20. However, the following paragraph from cppreference makes me think that it makes the program ill-formed.Moreover, it makes error messages shorter on non-supported C++ versions with a not
constexprmethod error when you try to use it rather than a deeper error explaining why theconstexprfunction is invalid.OGRE_CPP23_CONSTEXPRis currently unused, and will be removed in the final version if I don't find need for the extra powers that .This code places the
dataarray in an anonymous union withx,y,z,wdata members in the legacy Vector bases. Accessing a union from it's inactive path is officially undefined; however, to my knowledge, it is defined as doing the obvious thing in all the major compilers. I am unsure if the strategy of doing pointer math inside a homogeneous struct currently used is defined according to the spec either.Does this look like an acceptable direction for things to go from your perspective as a maintainer, or should I look for an alternative strategy for
constexprsupport?fixes #3605