我有一个矩阵类,它支持使用运算符重载实现的标量值的操作。由于除了正在使用的运算符之外,每个重载的运算符函数都具有相同的主体,因此我决定创建一个通用函数,该函数将接受函数以及矩阵和标量值来合并我的代码。
这是泛型函数,它是从重载的加法运算符函数调用的:
// Generic function to take care of matrix operations
template<typename T, typename F>
Matrix<T> scalar_operation(const Matrix<T> &a, const T b, F f) {
std::vector<std::vector<T> > new_els = a.elements;
typename std::vector<std::vector<T> >::iterator it = new_els.begin();
typename std::vector<T>::iterator it_in;
for (; it != new_els.end(); ++it) {
it_in = it->begin();
for (; it_in != it->end(); ++it_in) {
*it_in = f(*it_in, b);
}
}
return Matrix<T>(new_els);
}
// Add scalar to all values in Matrix
template<typename T>
Matrix<T> operator+(const Matrix<T> &a, const T b) {
return scalar_operation(a, b, std::plus<T>());
}
以下是矩阵类中声明的函数:
template<class T>
class Matrix {
template<typename F>
friend Matrix<T> scalar_operation(const Matrix<T> &a, const T b, F f);
friend Matrix<T> operator+<>(const Matrix<T> &a, const T b);
friend Matrix<T> operator-<>(const Matrix<T> &a, const T b);
friend Matrix<T> operator*<>(const Matrix<T> &a, const T b);
friend Matrix<T> operator/<>(const Matrix<T> &a, const T b);
当我单独实现重载的运算符函数时,它们有效,但是通过这种实现,我得到以下编译器错误:
Undefined symbols for architecture x86_64:
"Matrix<float> scalar_operation<std::__1::plus<float> >(Matrix<float> const&, float, std::__1::plus<float>)", referenced from:
Matrix<float> operator+<float>(Matrix<float> const&, float) in matrix_test-3188cd.o
ld: symbol(s) not found for architecture x86_64
我想我的错误与Matrix<float> scalar_operation<std::__1::plus<float> >(
行有关,因为看起来链接器正在搜索带有此标头的函数,这与我在文件中声明的方式略有不同,但我尝试修改我的声明,它会引发其他错误。
为什么我收到此错误,我该如何解决?谢谢!
编辑:为了消除一些困惑,所有代码都已在头文件中实现,因为它是一个模板化的类。没有相应的.cpp文件。
答案 0 :(得分:0)
代码有以下问题:类Matrix
声明了友元函数friend template<typename F> scalar_operation(...)
(是的,朋友关键字不仅表示私有访问,它还声明了一个函数),但是没有这样的函数在外部范围内。只有template<typename T, typename F> scalar_operation
,不符合朋友Matrix的声明。为什么?让我们尝试使用float
和std::plus<float>
进行伪代码实例化(为了简洁,省略了返回值和参数):
friend scalar_operation<std::plus<float>>(...)
和
scalar_operation<float, std::plus<float>>(...)
。
我们可以看到他们是不同的。所以在编译期间我们没有问题:我们有适当的朋友scalar_operation声明,它满足operator+
内的调用约定。但是没有对这种声明的定义,并且我们在链接时遇到问题。解决方案是一个适当的朋友声明:
template<typename TT, typename F>
friend Matrix<TT> scalar_operation(const Matrix<TT> &, const TT, F);