wlav / cppyy

Other
400 stars 41 forks source link

Default template arguments seem to break subsequent instantiations of the same template #78

Open tmadlener opened 2 years ago

tmadlener commented 2 years ago

This is potentially related to what has already been reported in #71, but I am not entirely sure. It was also initially reported in the root-forum in this thread

The thread has a workaround for the issue.

I have made the minimal reproducer there slightly smaller and posted that version below here. The underlying issue is unchanged (as far as I can tell).

Essentially what breaks is the following:

import cppyy

cppyy.cppdef('''
#include <type_traits>

struct RecoParticle {
  float x;
  float E;
  float M;
};

struct LorentzVM {
  float x;
  float M;
};

struct LorentzVE {
  float x;
  float E;
};

namespace detail {
  struct LorentzVMTag { using type = LorentzVM; };
  struct LorentzVETag { using type = LorentzVE; };

  template <typename ParticleT, typename LorentzVTag>
  inline typename LorentzVTag::type p4(ParticleT const& particle, LorentzVTag*) {
    if constexpr (std::is_same_v<typename LorentzVTag::type, LorentzVM>) {
      return LorentzVM{particle.x, particle.M};
  } if constexpr (std::is_same_v<typename LorentzVTag::type, LorentzVE>) {
      return LorentzVE{particle.x, particle.E}; 
  }
}
} // namespace detail

constexpr static detail::LorentzVMTag UseMass;
constexpr static detail::LorentzVETag UseEnergy;

template<typename ParticleT, typename LorentzVTag = detail::LorentzVMTag>
inline auto p4(ParticleT const& particle, LorentzVTag tag = UseMass) {
  return detail::p4(particle, &tag);
}
''')

p = cppyy.gbl.RecoParticle()
p.M = 125
p.E = 3.14

p4_M = cppyy.gbl.p4(p)  # this works
p4_E = cppyy.gbl.p4(p, cppyy.gbl.UseEnergy) # this does not