gcc - clang rejects a template `/` operator but gnu c++ accepts it -
in context of unit management scientific programming, managing following class:
template <class unitname> class quantity { double value; public: quantity(double val = 0) : value(val) {} quantity(const quantity &) {} quantity & operator = (const quantity &) { return *this; } double get_value() const noexcept { return value; } operator double() const noexcept { return value; } template <class srcunit> quantity(const quantity<srcunit> &) { // here conversion done } template <class srcunit> quantity & operator = (const quantity<srcunit> &) { // here conversion done return *this; } template <class tgtunit> operator tgtunit() const { tgtunit ret; // here conversion done return ret; } template <class u, class ur> quantity<ur> operator / (const quantity<u> & rhs) const { return quantity<ur>(value / rhs.value); } };
although class more complex, think put enough information in order describe problem:
now consider following code snippet:
struct km_h {}; struct km {}; struct hour {}; quantity<km_h> compute_speed(const quantity<km> & dist, const quantity<hour> & time) { quantity<km_h> v = dist/time; return v; }
this code accepted gnu c++
compiler , runs well. last template operator /
called.
but rejected clang++
compiler (v 3.8.1) following message:
test-simple.cc:53:26: error: use of overloaded operator '/' ambiguous (with operand types 'const quantity<km>' , 'const quantity<hour>') quantity<km_h> v = dist/time; ~~~~^~~~~ test-simple.cc:53:26: note: built-in candidate operator/(__int128, unsigned long long) test-simple.cc:53:26: note: built-in candidate operator/(unsigned long, long double)
so questions be: why clang++
rejects it? valid code? or gnu c++
should reject it?
in case code valid, how modify in order clang++
accept it?
i believe clang right reject code†, gcc doesn't want (both dist
, time
implicitly convertible double
† , gcc believes builtin operator/(double, double)
best viable candidate). problem is, wrote:
template <class u, class ur> quantity<ur> operator / (const quantity<u> & rhs) const
what ur
? it's non-deduced context - attempting invoke operator dist / time
deduction failure. candidate never considered. in order use it, you'd have explicitly provide ur
so:
dist.operator/<hour, km_h>(time); // explicitly providing ur == km_h
since that's awful, can't have ur
deduced template argument - have provide metafunction of 2 units:
template <class u> quantity<some_mf_t<unitname, u>> operator/(quantity<u> const& ) const;
with some_mf_t
defined.
†you have both operator double()
, template <class t> operator t()
, means builtin operator/
s equally viable candidates (they're non-template, exact matches).
†having operator double()
sort of defeats purpose of writing type safe units, no?
Comments
Post a Comment