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

Popular posts from this blog

jOOQ update returning clause with Oracle -

java - Warning equals/hashCode on @Data annotation lombok with inheritance -

java - BasicPathUsageException: Cannot join to attribute of basic type -