将函数放入命名空间会中断 std::vector 的使用

putting function inside a namespace breaks use of std::vector

我写了一个函数来计算 std::vector<double>

的逐元素平方根
#include <cmath>
#include <vector>
namespace pcif {
    std::vector<double> sqrt(const std::vector<double>& d) {
        std::vector<double> r;
        r.reserve(d.size());
        for (size_t i{ 0 }; i < r.size(); ++i) {
            r.push_back(sqrt(d[i]));
        }
        return r;
    }
}

我收到错误(全部指向 r.push_back 行):

如果我删除命名空间,所有编译都不会出现任何问题。

我做错了什么?有更好的方法吗?

我在 Visual Studio 2019,C++17 工作。

.

后续问题:

使用完全限定的 std::sqrt() 可以解决这个问题。为什么它在我没有命名空间的原始情况下工作?我不能只调用vector<double>,为什么我可以调用sqrt

正如评论中已经提到的那样,您应该显式调用 ::sqrt()(或从 std namespace、std::sqrt()),否则您将递归调用自己的sqrt() 参数错误的函数。

原因是在全局名称space中,已经存在一个名为sqrt()的匹配函数(这就是它在pcif名称space之外工作的原因) ).
一旦你进入 pcif namespace,除了你正在编写的那个之外,没有定义其他 sqrt() 重载,因此递归有错误的参数(重载在相同的查找范围)。
要解决这个问题,您可以显式调用全局名称space ::sqrt() 的函数或std 名称space std::sqrt().[= 中定义的函数。 27=]

此外,您还应该将循环条件从 i < r.size() 更改为 i < d.size(),因为 r 为空。 请记住 reserve(n) 不会更改容器的大小,它只会分配必要的 space 以便能够存储至少 n 个元素而无需重新分配(即只有容量已更改)。
您可能有兴趣查看 documentation.

问题是由于重载解析,在调用表达式sqrt(d[i])中,名字sqrt 指的是您所在的同一函数。并且由于参数 d[i] 的类型与自定义函数的参数 d 的类型不匹配,您会收到上述错误.

解决这个问题,您可以限定调用表达式std::中的名称sqrt sqrt(d[i]) 这样它看起来像:

namespace pcif {
    std::vector<double> sqrt(const std::vector<double>& d) {
        std::vector<double> r;
        r.reserve(d.size());
        for (size_t i{ 0 }; i < d.size(); ++i) {
//----------------------vvv--------------------> std:: added here
            r.push_back(std::sqrt(d[i]));
        }
        return r;
    }
}

通过使用 std::,我们告诉编译器在 std 命名空间 中查找名为 sqrt 的函数。