我打算实现我的“稀疏向量”和“向量”类的乘法运算符。以下简化的代码演示显示了我的问题
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();
}
};
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;
}
};
main.cpp 中的测试代码:
#include "Vector.hpp"
#include "SpVec.hpp"
#include <iostream>
int main()
{
Vector<double> v;
SpVec<double> spv;
std::cout << spv * v;
return 0;
}
我使用以下代码构建测试程序
g++ main.cpp -o test
给出模棱两可的模板推导错误
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
我希望#2
方法定义更接近于我的调用。
请帮助我了解模棱两可的错误是如何产生的以及如何解决该问题。
答案 0 :(得分:3)
我想到了另一种想法,即先前类型信息Scalar
可以与c++11
标准库结构SFAINE feature启用的std::enable_if
一起使用。
代码:
Vector.hpp
#pragma once
#include <iostream>
#include <type_traits>
template <typename T>
class Vector
{
public:
Vector() {}
template <typename Scalar>
typename std::enable_if<std::is_arithmetic<Scalar>::value, Vector<T>>::type
operator*(const Scalar &rhs) const// #1
{
std::cout << "Vector * Scalar called." << std::endl;
return Vector();
}
template <typename Scalar>
inline friend typename std::enable_if<std::is_arithmetic<Scalar>::value, Vector<T>>::type
operator*(const Scalar &lhs, const Vector &rhs)
{
std::cout << "Scalar * Vector called." << std::endl;
return Vector();
}
};
SpVec.hpp
#pragma once
#include "Vector.hpp"
#include <iostream>
template <typename T>
class SpVec
{
public:
SpVec() {}
template <typename U>
inline double operator*(const Vector<U> &rhs) const // #2 as member function
{
std::cout << "SpVec * Vector called" << std::endl;
return 0.0;
}
template <typename U>
inline friend double operator*(const Vector<U> &lhs, const SpVec &rhs)
{
std::cout << "Vector * SpVec called" << std::endl;
return 0.0;
}
};
main.cpp
#include "SpVec.hpp"
#include "Vector.hpp"
#include <iostream>
int main()
{
Vector<double> v;
SpVec<double> spv;
double a = spv * v;
a = v * spv;
Vector<double> vt;
vt = v * 2.0;
vt = 2.0 * v;
return 0;
}
使用c++11
g++ -std=c++11 main.cpp -o test
结果:
SpVec * Vector called.
Vector * SpVec called.
Vector * Scalar called.
Scalar * Vector called.
答案 1 :(得分:0)
operator*
的参数为SpVec<double>
和Vector<double>
。可以解决
operator*(const Scalar &a, const Vector &rhs)
,其中scalar
为SpVec<double>
,rhs
为Vector<double>
。
它也可以解决
operator*(const SpVec &spv, const Vector<U> &v)
,其中spv为SpVec<double>
,而U
为double
。
解决此问题的一种方法是将Vector::operator*
设为非朋友功能。
Vector operator*(const Scalar &a) // #1
{
//The other argument here will be accessed using this pointer.
return Vector();
}
,您可以将其称为
int main()
{
Vector<double> v;
SpVec<double> spv;
std::cout << spv * v; // will call #2
v * spv; //will call #1
return 0;
}