编译期间未找到模板化函数

时间:2017-03-22 15:16:42

标签: c++

我有一个矩阵类,它支持使用运算符重载实现的标量值的操作。由于除了正在使用的运算符之外,每个重载的运算符函数都具有相同的主体,因此我决定创建一个通用函数,该函数将接受函数以及矩阵和标量值来合并我的代码。

这是泛型函数,它是从重载的加法运算符函数调用的:

    // 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文件。

1 个答案:

答案 0 :(得分:0)

代码有以下问题:类Matrix声明了友元函数friend template<typename F> scalar_operation(...)(是的,朋友关键字不仅表示私有访问,它还声明了一个函数),但是没有这样的函数在外部范围内。只有template<typename T, typename F> scalar_operation,不符合朋友Matrix的声明。为什么?让我们尝试使用floatstd::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);