模板扣除投诉暧昧的候选人

Rub*_*bin 6 c++ templates metaprogramming ambiguous

我打算实现我的"稀疏矢量"和"矢量"类的乘法运算符.以下简化的代码演示显示了我的问题

Vector.hpp中的Vector类

#pragma once

template <typename T>
class Vector 
{
public:
    Vector() {}

    template <typename Scalar>
    friend Vector operator*(const Scalar &a, const Vector &rhs)     // #1
    {
        return Vector();
    }
};
Run Code Online (Sandbox Code Playgroud)

SpVec.hpp中的Sparse Vector类

#pragma once
#include "Vector.hpp"

template <typename T>
class SpVec 
{
public:
    SpVec() {}

    template <typename U>
    inline friend double operator*(const SpVec &spv, const Vector<U> &v)   // #2
    {
        return 0.0;
    }
};
Run Code Online (Sandbox Code Playgroud)

main.cpp中的测试代码:

#include "Vector.hpp"
#include "SpVec.hpp"


#include <iostream>

int main() 
{
    Vector<double> v;

    SpVec<double> spv;

    std::cout << spv * v;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用它构建了测试程序

g++ main.cpp -o test
Run Code Online (Sandbox Code Playgroud)

这给出了模糊的模板推导错误

main.cpp: In function ‘int main()’:
main.cpp:13:26: error: ambiguous overload for ‘operator*’ (operand types are ‘SpVec<double>’ and ‘Vector<double>’)
        std::cout << spv * v;
                    ~~~~^~~
In file included from main.cpp:2:0:
SpVec.hpp:12:26: note: candidate: double operator*(const SpVec<T>&, const Vector<U>&) [with U = double; T = double]
    inline friend double operator*(const SpVec &spv, const Vector<U> &v)   // #2
                        ^~~~~~~~
In file included from main.cpp:1:0:
Vector.hpp:10:19: note: candidate: Vector<T> operator*(const Scalar&, const Vector<T>&) [with Scalar = SpVec<double>; T = double]
    friend Vector operator*(const Scalar &a, const Vector &rhs)     // #1
Run Code Online (Sandbox Code Playgroud)

我希望#2方法定义更接近我的调用.

请帮助我理解模糊错误是如何产生的,以及如何解决问题.

Gau*_*gal 0

的参数operator*是SpVec<double>和Vector<double>。可以解决为

operator*(const Scalar &a, const Vector &rhs)与scalarasSpVec<double>和rhsas Vector<double>。

它还可以解决

operator*(const SpVec &spv, const Vector<U> &v)与 spv asSpVec<double>和Uas double。

解决这个问题的一种方法是转向Vector::operator*非友元函数。

Vector operator*(const Scalar &a)     // #1
{
    //The other argument here will be accessed using this pointer.
    return Vector();
}
Run Code Online (Sandbox Code Playgroud)

你可以称之为

int main() 
{
   Vector<double> v;
   SpVec<double> spv;
   std::cout << spv * v; // will call #2
   v * spv;              //will call #1
   return 0;
}
Run Code Online (Sandbox Code Playgroud)