在 C++ 中将范数定义为 vector class 的成员函数

Define norm as member function of vector class in C++

我正在尝试用 C++ 编写自己的向量 class。特别是,我想将范数实现为成员函数。以下 classic 代码片段是我所做的:

#include <iostream>
#include <cmath>

template <typename T>
class vector{
private:
    T* elem;
    std::size_t _size;
public:
    vector(const std::size_t size) : elem{new T[size]}, _size{size} {}
    ~vector(){ delete[] elem;}
    std::size_t size() const { return _size;}
    T& operator[](std::size_t i){ return elem[i];}
    const T& operator[](std::size_t i) const{ return elem[i];}
    friend T norm();
};

template <typename T>
T vector::norm(){
    T sum{0};
    for (auto i=0u;i<_size;++i){
        sum+=elem[i];
    }
    return std::sqrt(sum);
}

int main(){
    vector<double> v{10};
    for (auto i=0u;i<v.size();++i){
        v[i] = i;
    }

    std::cout << v.norm() <<std::endl;
    
    return 0;
}

显然,我可以在 class 内部定义函数 norm,但我想在外部定义它,因为原则上其中一个成员函数的主体可能有几行那么长。

一旦我尝试编译,编译器说:

但我不明白哪里出了问题,也不知道如何解决!特别是最后一点我不明白:我明确声明 norm() 为成员函数!我应该如何更改我的代码?

您将 norm() 声明为 friend 函数,因此它实际上不是 vector class 本身的成员。您告诉编译器某些外部 non-member 函数 T norm()vectorfriend 以便它可以访问 vector 的私有成员。但是你实际上并没有定义这样一个 T norm() 函数!

norm() 作为成员实现的正确方法,在 class 声明之外定义,应该是这样的:

template <typename T>
class vector{
    ...
public:
    ...
    T norm(); // <-- remove 'friend'!
};

template <typename T>
T vector<T>::norm(){ // <-- note the extra <T>!
    T sum{0};
    for (auto i = 0u; i < _size; ++i){
        sum += elem[i];
    }
    return std::sqrt(sum);
}

旁注:

您可以考虑使用 SFINAE 省略 norm() 的声明+定义 T 类型 std::sqrt() 不支持的类型(non-integers/floating-point 类型,例如字符串等)。

此外,您的 vector class 未实现 Rule of 3/5/0 以正确管理其内部数组。您需要向其添加适当的 copy/move 构造函数和 copy/move 赋值运算符。