将函数放入命名空间会中断 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
行):
- 无法从 'const _Ty' 转换为 'const std::vector<double,std::allocator>'
- error C2664: 'std::vector<double,std::allocator> pcif::sqrt(const std::vector<double,std::allocator> &)': 无法将参数 1 从 'const _Ty' 转换为 'const std::vector<double,std::allocator> &'
- class 'std::vector<double,std::allocator>' 的构造函数已声明 'explicit'
如果我删除命名空间,所有编译都不会出现任何问题。
我做错了什么?有更好的方法吗?
我在 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
的函数。
我写了一个函数来计算 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
行):
- 无法从 'const _Ty' 转换为 'const std::vector<double,std::allocator>'
- error C2664: 'std::vector<double,std::allocator> pcif::sqrt(const std::vector<double,std::allocator> &)': 无法将参数 1 从 'const _Ty' 转换为 'const std::vector<double,std::allocator> &'
- class 'std::vector<double,std::allocator>' 的构造函数已声明 'explicit'
如果我删除命名空间,所有编译都不会出现任何问题。
我做错了什么?有更好的方法吗?
我在 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
的函数。