No match for ‘operator<<' (probably due to my version of c++/gcc?)

huangapple go评论72阅读模式
英文:

No match for ‘operator<<’ (probably due to my version of c++/gcc?)

问题

I’m a C++ newbie. I’ve tried to set up NetBeans and run a c++ program in my MacBook Air via virtual machine (UTM) lately. It works well in my company's Linux desktop, but somehow it just doesn’t work in my virtual Linux. The source code is the same in these two platforms, but they have different compilation result. One is fine, and the other shows the error message below.

> error: no match for ‘operator<<’

I was wondering if it is due to the version mismatch or something similar of these two Linux environment. By the way, the author of this program has left the company, so I am doing my best to understand his code. I’ve seen several posts here about this exactly the same issue, but it seems none of those solutions can work with my situation where this source code works well in one Linux while it doesn’t work in another one.

Below is the error message and relevant source codes. Could you please help me look into them? Thanks a lot!

Source code:

class logger
    {
      public:
        typedef std::ostringstream collector_stream_type;

      private:
        collector_stream_type _os;
        log_levels _messageLevel;

       public:
           logger(const logger &amp; r) : _messageLevel(r._messageLevel)
              {
                   if ( do_log() ) _os &lt;&lt; r._os; // this is where the error occurs.
               }
    }

Error / Warning message from NetBeans

> In file included from
> * error: no match for ‘operator<<’ (operand types are ‘MySoftware::log::logger::collector_stream_type’ {aka
> ‘std::__cxx11::basic_ostringstream<char>’} and ‘const
> collector_stream_type’ {aka ‘const
> std::__cxx11::basic_ostringstream<char>’})
> * note: cannot convert ‘r.MySoftware::log::logger::_os’ (type ‘const collector_stream_type’ {aka ‘const
> std::__cxx11::basic_ostringstream<char>’}) to type ‘const
> std::error_code&’
> * note: ‘const collector_stream_type’ {aka ‘const std::__cxx11::basic_ostringstream<char>’} is not derived from ‘const
> std::complex<_Tp>’
> * note: cannot convert ‘((MySoftware::log::logger*)this)->MySoftware::log::logger::_os’ (type
> ‘MySoftware::log::logger::collector_stream_type’ {aka
> ‘std::__cxx11::basic_ostringstream<char>’}) to type ‘std::byte’
> * note: candidate: ‘operator<<(int, int)’ (built-in)
> * note: ‘const collector_stream_type’ {aka ‘const std::__cxx11::basic_ostringstream<char>’} is not derived from ‘const
> std::__shared_ptr<_Tp, _Lp>’
> * note: deduced conflicting types for parameter ‘_CharT’ (‘char’ and ‘std::__cxx11::basic_ostringstream<char>’...

英文:

I’m a C++ newbie. I’ve tried to set up NetBeans and run a c++ program in my MacBook Air via virtual machine (UTM) lately. It works well in my company's Linux desktop, but somehow it just doesn’t work in my virtual Linux. The source code is the same in these two platforms, but they have different compilation result. One is fine, and the other shows the error message below.

> error: no match for ‘operator<<’

I was wondering if it is due to the version mismatch or something similar of these two Linux environment. By the way, the author of this program has left the company, so I am doing my best to understand the his code. I’ve seen several posts here about this exactly the same issue, but it seems none of those solutions can work with my situation where this source code works well in one Linux while it doesn’t work in another one.

Below is the error message and relevant source codes. Could you please help me look into them? Thanks a lot!

Source code:

class logger
    {
      public:
        typedef std::ostringstream collector_stream_type;

      private:
        collector_stream_type _os;
        log_levels _messageLevel;

       public:
           logger(const logger &amp; r) : _messageLevel(r._messageLevel)
              {
                   if ( do_log() ) _os &lt;&lt; r._os; // this is where the error occurs.
               }
    }

Error / Warning message from NetBeans

> In file included from
> * error: no match for ‘operator<<’ (operand types are ‘MySoftware::log::logger::collector_stream_type’ {aka
> ‘std::__cxx11::basic_ostringstream<char>’} and ‘const
> collector_stream_type’ {aka ‘const
> std::__cxx11::basic_ostringstream<char>’})
> * note: cannot convert ‘r.MySoftware::log::logger::_os’ (type ‘const collector_stream_type’ {aka ‘const
> std::__cxx11::basic_ostringstream<char>’}) to type ‘const
> std::error_code&’
> * note: ‘const collector_stream_type’ {aka ‘const std::__cxx11::basic_ostringstream<char>’} is not derived from ‘const
> std::complex<_Tp>’
> * note: cannot convert ‘((MySoftware::log::logger*)this)->MySoftware::log::logger::_os’ (type
> ‘MySoftware::log::logger::collector_stream_type’ {aka
> ‘std::__cxx11::basic_ostringstream<char>’}) to type ‘std::byte’
> * note: candidate: ‘operator<<(int, int)’ (built-in)
> * note: ‘const collector_stream_type’ {aka ‘const std::__cxx11::basic_ostringstream<char>’} is not derived from ‘const
> std::__shared_ptr<_Tp, _Lp>’
> * note: deduced conflicting types for parameter ‘_CharT’ (‘char’ and ‘std::__cxx11::basic_ostringstream<char>’...

答案1

得分: 3

这很可能一直都是错误的(假设在您的代码中没有某个用户定义的 operator<< 重载候选项隐藏在某处)。

标准库中从未存在过接受两个 std::ostringstream 或相关类型作为参数的 operator<< 重载。

相反,在 C++11 之前,所选择的重载将是:

std::basic_ostream::operator<<(const void*)

因为右侧的 std::ostringstream 类型 _os << r._os 的基类 std::basic_ios 有一个将 r._os 隐式转换为 void* 的转换函数。如果流处于 fail() 状态,结果将是一个空指针,否则是任何其他指针值。

结果是,如果 r._os 处于 fail() 状态,_os << r._os 将向 _os 写入空指针的数值表示,否则写入其他指针值的数值表示。

这似乎不是预期的行为。

自从 C++11 以来,转换函数已更改为转换为 bool,并且已被标记为 explicit,因此不再适用于隐式转换使用 operator<<(const void*) 重载。这个变化的目的是防止类似的错误。


附注:错误消息不是来自 Netbeans。Netbeans 是您的集成开发环境。错误消息来自您的编译器,根据您的描述似乎是 GCC。

英文:

This was probably always wrong (assuming there isn't some user-defined operator&lt;&lt; overload candidate hiding somewhere in your code).

There is and never has been any overload of operator&lt;&lt; in the standard library that would take two std::ostringstream or related types as parameters.

Instead before C++11 the chosen overload would be

std::basic_ostream::operator&lt;&lt;(const void*)

because the std::basic_ios base class of the right-hand std::ostringstream of _os &lt;&lt; r._os had a conversion function to void* that could implicitly convert r._os to void*. The result would be a null pointer if the stream is in a fail() state and any other pointer value otherwise.

The result is that _os &lt;&lt; r._os will write to _os a numeric representation of a null pointer if r._os is in a fail() state and any other numeric representation of a pointer value otherwise.

That doesn't seem intended.

Since C++11 the conversion function has been changed to convert to bool instead and has been made explicit so that it isn't viable any more for an implicit conversion to use the operator&lt;&lt;(const void*) overload. The change is meant to prevent exactly such mistakes.


Side note: The error messages are not from Netbeans. Netbeans is your IDE. The error messages are from your compiler, which seems to be GCC according to what you wrote.

huangapple
  • 本文由 发表于 2023年6月26日 04:06:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定