C++ 编译器选择输出流运算符<<的错误重载
C++ Compiler picks wrong overload of output stream operator <<
我有一个非常简单的内联助手类IpAddress
,它有两个重载运算符<lt;将对象序列化为一组自定义二进制流(运算符作为模板函数),或将其输出到std::ostream(非模板运算符函数)。
#include <cstdint>
#include <string>
#include <array>
#include <iostream>
#include <sstream>
typedef uint8_t byte;
class IpAddress: public std::array<byte,4>
{
// ...
template<class S>
inline friend S& operator<<(S& left, const IpAddress& right) {
left.setBytes(right.data(), 4);
return left;
}
inline friend std::ostream& operator<< (std::ostream& left, const IpAddress& right) {
// do stuff eligible for an ostream
return left;
}
inline operator std::string() {
std::stringstream stream;
stream << *this;
return stream.str();
}
}
正如您所看到的,还有一个运算符可以将地址转换为字符串。不幸的是,<lt;内部调用选择了错误的运算符<lt;(模板一),导致编译器错误:
error: C2039: 'setBytes' : is not a member of 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>'
为什么编译器(在这种情况下是MSVC)使用非工作体选择了错误的重载?为什么不使用"更专业"的std::ostream操作符呢?我该如何改变这种行为?谢谢
您没有发布一个完整的、可编译的示例,所以我看不到调用站点。
然而,这个问题很可能是因为无论你流到什么地方,都不完全是ostream
。它很可能是从ostream
中派生出来的。在这种情况下,template T
将是更好的匹配。
编辑:
撇开风格评论不谈(它们是对的,你最好听听),这里有一个解决方案:
#include <iostream>
#include <utility>
#include <cstdint>
#include <array>
#include <sstream>
template<class T> static constexpr bool IsAnOstream = std::is_base_of<std::decay_t<T>, std::ostream>::value;
using byte = std::uint8_t;
struct IpAddress: public std::array<byte,4>
{
// ...
template<class S, std::enable_if_t<not IsAnOstream<S>>* = nullptr>
friend S& operator<<(S& left, const IpAddress& right) {
left.setBytes(right.data(), 4);
return left;
}
friend std::ostream& operator<< (std::ostream& left, const IpAddress& right) {
// do stuff eligible for an ostream
return left;
}
/*
* this is a bad idea - it can lead to all kinds of confusion
*
inline operator std::string() {
std::stringstream stream;
stream << *this;
return stream.str();
}
*/
};
// this is better - it's less surprising.
std::string to_string(const IpAddress& r)
{
std::stringstream stream;
stream << *this;
return stream.str();
}
struct MyStream
{
void setBytes(const uint8_t* p, size_t len) {}
};
int main()
{
IpAddress a;
MyStream s;
std::cout << a;
s << a;
return 0;
}
相关文章:
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- &lt;&lt;操作员在C 中超载错误
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- '&lt;'''&lt;'''&quot的模板类错误''令牌”
- 在尝试超载&lt;&lt;时链接错误2005和1169操作员
- 错误:没有匹配'运算符<<"在'std::cout
- 过载<<比如cout错误
- 重载& lt; & lt;为什么我得到以下错误
- 重载ostream&时转换错误无效;operator< & lt;
- 重载<<运算符错误C2804:二进制'运算符<<'参数太多
- 编译器错误,包括'<'代币
- 重载& lt; & lt;错误