在多参数情况下使用转换构造函数

Using converting constructor in multiple parameter case

我在看这个视频 CppCon 2018:Dan Saks“结交新朋友”please look here

我在这个谈话中,他指的是一个(假设的)有理数 class(有 分子和分母作为私有成员,所有的计算都围绕着 围绕这个。我正在尝试实施本次演讲中提到的任何内容,只是为了 很好地理解模板。

我知道,Dan 提到了一个执行乘法的函数 int*rational

//~ rational.h
template <typename> class rational;
template <typename T> std::ostream& operator<<(std::ostream&, const rational<T> &);
template <typename T> rational<T> operator*(const rational<T>&, const rational<T>&);

template <typename T>
class rational {
    friend std::ostream& operator<<<T>(std::ostream&, const rational<T>&);
    friend rational<T> operator*<T>(const rational<T>&, const rational<T>&);
    public:
        rational(); 
        rational(T num);
        rational(T num, T den); 
        rational(const rational &ro);

        rational &operator+=(const rational &ro);
        rational &operator*=(const rational &ro);
...
...
    private:
        T num, den;
};

// implements operator*
template <typename T>
rational<T> operator*(const rational<T> &lo, const rational<T> &ro) {
    rational<T> result(ro);
    result *= lo;
    return result;
}

然后,我们有 main

//~ temp.cpp
#include <iostream>
#include "rational.h"

using namespace std;

int main(int argc, char *argv[]) {
    rational<int> r1(1,3);
    rational<int> r2(5,6);

    cout << "r1=" << r1 << ", r2=" << r2 << endl;

    rational<int> r3(3);

    r3 = 3*r3;

    cout << r3 << endl;

    return 0;
}

但是,当我构建它时,出现错误:

onkar@TITAN:~/cc/test$ make
g++ -g -Wno-unused-variable -Wno-unused-but-set-variable -std=c++11 -Wall -c test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:14:8: error: no match for ‘operator*’ (operand types are ‘int’ and ‘rational<int>’)
   14 |  r3 = 3*r3;
      |       ~^~~
      |       | |
      |       | rational<int>
      |       int
In file included from test.cpp:2:
rational.h:58:13: note: candidate: ‘template<class T> rational<T> operator*(const rational<T>&, const rational<T>&)’
   58 | rational<T> operator*(const rational<T> &lo, const rational<T> &ro) {
      |             ^~~~~~~~
rational.h:58:13: note:   template argument deduction/substitution failed:
test.cpp:14:9: note:   mismatched types ‘const rational<T>’ and ‘int’
   14 |  r3 = 3*r3;
      |         ^~
make: *** [Makefile:2: test] Error 1
onkar@TITAN:~/cc/test$ 

现在,我明白了这个错误(转换构造函数接受单个参数和所有参数) 但问题是:

如何确保 r3 = 3*r3; 正常工作(而且我不必调用(看起来很奇怪)r3 = rational<int>(3)*r3 反正我总能做到。

template argument deduction 中不考虑隐式转换。给定 3*r3,基于第一个函数参数(即 3)的 T 的模板参数推导失败;不考虑从 intrational<int> 的隐式转换。

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

您可以将 operator* 更改为非模板,它不会出现此类问题,并且隐式转换会按您的预期工作。

template <typename> class rational;
template <typename T> std::ostream& operator<<(std::ostream&, const rational<T> &);

template <typename T>
class rational {
    friend std::ostream& operator<<<T>(std::ostream&, const rational<T>&);
    friend rational<T> operator*(const rational<T> &lo, const rational<T> &ro) {
        rational<T> result(ro);
        result *= lo;
        return result;
    }
    public:
        rational(); 
        rational(T num);
        rational(T num, T den); 
        rational(const rational &ro);

        rational &operator+=(const rational &ro);
        rational &operator*=(const rational &ro);
...
...
    private:
        T num, den;
};