Compilation error in pythia8312, using clang++ v15 --std=c++20

Dear Pythia authors,

I'd like to report an error I came across compiling pythia 8312 with clang 15, using the --std=c++20 flag. Here's what the compiler has to say:

clang++ src/FJcore.cc -o tmp/FJcore.o -c -MD -Iinclude -O2 -std=c++20 -pedantic -W -Wall -Wshadow -fPIC -pthread -DFJCORE_HAVE_LIMITED_THREAD_SAFETY In file included from src/FJcore.cc:83: In file included from include/Pythia8/FJcore.h:725: In file included from /usr/bin/../lib/gcc/aarch64-redhat-linux/13/../../../../include/c++/13/vector:66: /usr/bin/../lib/gcc/aarch64-redhat-linux/13/../../../../include/c++/13/bits/stl_vector.h:370:35: error: arithmetic on a pointer to an incomplete type 'fjcore::ClosestPair2D::Point' 370 | _M_impl._M_end_of_storage - _M_impl._M_start); | ~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ...

The issue seems to be that the class Point is forward declared, but then used in the template of a std::vector. This is in principle illegal, but most compilers seem to give it a pass; I have not managed to get gcc to give a similar error, and clang only fails on newer versions and the latest cxxstd=20 . Here is a very minimal reproducer, you can check the compiler situation yourself:

https://godbolt.org/z/KbTcvcYW8

The solution seem to be to move the definition of Point inside of ClosestPair2D - It needs a bit of reorganization of the typedefs and the Shuffle class, but the patch below compiles. This is however just a suggestion and I have not done any extensive testing and checks with other compilers!

Cheers, Valentin

PS: Obviously, feel free to publish the answer publicly on your service desk

--- src/FJcore.cc.orig 2024-10-23 13:59:55.670579980 +0200 +++ src/FJcore.cc 2024-10-23 13:55:34.512117683 +0200 @@ -758,7 +758,6 @@ const Coord2D & left_corner, const Coord2D & right_corner, const unsigned int max_size); static const unsigned int _nshift = 3;

  • class Point; // will be defined below template class triplet { public: inline const T & operator[](unsigned int i) const {return _contents[i];}; @@ -766,10 +765,11 @@ private: T _contents[_nshift]; };
  • class Point; class Shuffle { public: unsigned int x, y;
  • Point * point;
  • ClosestPair2D::Point * point; bool operator<(const Shuffle &) const; void operator+=(unsigned int shift) {x += shift; y+= shift;}; }; @@ -777,6 +777,17 @@ typedef Tree::circulator circulator; typedef Tree::const_circulator const_circulator; triplet<SharedPtr > _trees;
  • class Point {
  • public:
  • Coord2D coord;
  • Point * neighbour;
  • double neighbour_dist2;
  • ClosestPair2D::tripletClosestPair2D::circulator circ;
  • unsigned int review_flag;
  • double distance2(const Point & other) const {
  •  return coord.distance2(other.coord);
  • };
  • }; SharedPtr _heap; std::vector _points; std::stack<Point *> _available_points; @@ -797,17 +808,6 @@ triplet _rel_shifts; // shifts relative to previous shift unsigned int _cp_search_range; }; -class ClosestPair2D::Point { -public:
  • Coord2D coord;
  • Point * neighbour;
  • double neighbour_dist2;
  • triplet circ;
  • unsigned int review_flag;
  • double distance2(const Point & other) const {
  • return coord.distance2(other.coord);
  • }; -}; inline bool floor_ln2_less(unsigned x, unsigned y) { if (x>y) return false; return (x < (x^y)); // beware of operator precedence...
Assignee Loading
Time tracking Loading