Skip to content

Latest commit

 

History

History
47 lines (38 loc) · 1.69 KB

File metadata and controls

47 lines (38 loc) · 1.69 KB

条款46:需要类型转换时请为模板定义非成员函数

本条款首先以一个看似无害的改动扩充条款24的讨论;本条款将Rational和operator*模板化了:

template <typename T>
class Rational {
public:
  Rational(const T& numerator = 0, const T& denominator = 1);
  const T numerator() const;
  const T denominator() const;
  ...
};
template <typename T>
const Rational<T> operator* (const Rational<T>& lhs, const Rational<T>& rhs)
{...}

我们希望以下代码顺利通过编译,operator* 支持交换律:

Rational oneHalf(1, 2);
Rational result = oneHalf * 2;  // error!

编译器无法推导出T是什么类型, operator* 无法被正确实例化。oneHalf的类型是 Rational<int> ,所以T一定是int,而 2 无法推导出T的类型,因为在template实参推导的过程中从不将隐式类型转换函数纳入考虑。

template class内的friend声明可以指定某个特定函数,那么 operator* 可以是 Rational<T> 的friend函数。类模板并不依赖模板实参推导,因此,令 Rational<T> 声明 operator* 为friend函数可以简化整个问题:

template <typename T>
class Rational {
public:
  ...
  friend const Rational operator*(const Rational& lhs, 
                                  const Rational& rhs) {
    return Rational(lhs.numerator() * rhs.numerator(),
                    lhs.denominator() * rhs.denominator());
  }
};

现在,我们所期望的正常运行起来。

请记住

  • 当我们编写一个class template,而它所提供的与模板相关的函数支持所有参数的隐式类型转换时,请将那些函数定义为class template的内部friend函数。