【发布时间】:2018-08-18 01:44:54
【问题描述】:
当不同的编译器行为不同时会出现问题。可惜,PVS没有告诉我下面的危险情况。
我有一些重载的函数,但我忘记编写前向声明。所以 Visual Studio 编译一个程序,而其他编译器编译另一个。
我的功能:
// For simple types (i.e. int, bool, char) and plain old data
template <typename T>
void serialize(T pod, std::ostream& out) {
std::cout << "pod\n";
out.write(reinterpret_cast<const char*>(&pod), sizeof(T));
}
void serialize(const std::string& str, std::ostream& out) {
std::cout << "string\n";
serialize(str.size(), out);
out.write(str.data(), str.size());
}
template <typename T>
void serialize(const std::vector<T>& data, std::ostream& out) {
std::cout << "vector\n";
serialize(data.size(), out);
for (const T& elem : data) {
serialize(elem, out); // <== runs POD serialization for map :(
}
}
template <typename T1, typename T2>
void serialize(const std::map<T1, T2>& data, std::ostream& out) {
std::cout << "map\n";
serialize(data.size(), out);
for (const auto& p : data) {
serialize(p.first, out);
serialize(p.second, out);
}
}
我用代码对此进行了测试:
std::vector<std::map<int, int>> v;
v.emplace_back();
v[0][1] = 2;
std::stringstream ss;
serialize(v, ss);
在 VS 中测试没问题(调试版和发布版):
vector
pod [size of vector]
map
pod [size of map]
pod [key = 1]
pod [value = 2]
但突然我的同事告诉我,根本没有任何工作。
我已经在不同的编译器上进行了测试(感谢 Ideone 网站)。所有行为都错误(gcc 4.3.2、6.3;clang 4.0):
vector
pod [size of vector]
pod [map]
当然,在所有函数之前放置前向声明后,所有编译器中的一切都变得正确。
我要求实施有关前向声明的警告。
【问题讨论】:
-
嗯...“这只是对工作不足的描述,而不是一个问题。错误报告和功能请求在 Stack Overflow 上不是主题。”是不是一样的情况?
-
编译器如何知道您打算转发声明这些函数?在您指出那里有一个非常好的重载(您的第一个模板的实例化)。您应该将您的第一个函数限制为仅使用 POD,如果它仅适用于 POD,那么编译器将找不到适合的重载并给出错误。
-
谢谢,我们会努力改进PVS-Studio的分析。
标签: c++ visual-studio g++ forward-declaration pvs-studio