clang拒绝模板`/`运算符,但gnu c接受它

在科学编程的单元管理环境中,我正在管理以下课程:

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 the conversion is done
  }

  template <class SrcUnit>
  Quantity & operator = (const Quantity<SrcUnit> &)
  {
    // here the conversion is done
    return *this;
  }

  template <class TgtUnit> operator TgtUnit() const
  {
    TgtUnit ret;
    // here the conversion is done
    return ret;
  }

  template <class U,class Ur>
  Quantity<Ur> operator / (const Quantity<U> & rhs) const
  {
    return Quantity<Ur>(value / rhs.value);
  }
};

虽然课程要复杂得多,但我认为我提供了足够的信息来描述我的问题:

现在考虑以下代码段:

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;
}

这段代码被gnu c编译器接受,运行良好.调用最后一个模板运算符.

但它被clang编译器(v 3.8.1)拒绝,并带有以下消息:

test-simple.cc:53:26: error: use of overloaded operator '/' is ambiguous (with operand
      types 'const Quantity<Km>' and '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)

所以我的问题是:为什么clang拒绝它?是一个有效的代码?或者gnu c应该拒绝它?

代码有效的情况下,如何修改它以便clang接受它?

解决方法

我相信铿锵是拒绝你的代码†的权利,但gcc实际上并没有做你想要的(dist和时间都可以隐含地转换为double‡而gcc认为内置运算符/(double,double)是最好的候选者).问题是,你写道:

template <class U,class Ur>
Quantity<Ur> operator / (const Quantity<U> & rhs) const

什么是Ur?这是一个非推断的上下文 – 所以试图调用此运算符只是dist / time是一个演绎失败.你的候选人从未被考虑过.为了实际使用它,您必须明确提供Ur,如下所示:

dist.operator/<Hour,km_h>(time); // explicitly providing Ur == km_h

由于这很糟糕,你不能将Ur推断为模板参数 – 你必须自己提供它作为两个单元的一些元函数

template <class U>
Quantity<some_mf_t<UnitName,U>> operator/(Quantity<U> const& ) const;

与some_mf_t一起定义.

†你有operator double()和template< class T>运算符T(),这意味着所有内置运算符都是同样可行的候选者(它们都是非模板,完全匹配).

‡让操作符double()类型失败了写入类型安全单元的目的,不是吗?

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...