为什么不能用ostream和map(或unordered_map)重载运算符<

问题描述 投票:0回答:1

我有一个从std :: ostringstream派生的类,并对喜欢流输出的运算符进行了编码<

enum class LogLevel { Debug, Infor, Notif, Warnn, Error, Fatal };
constexpr string_view LevelNames[] { "Debug", "Infor", "Notif", "Warnn", "Error", "Fatal" };
LogLevel sysLogLevel { LogLevel::Debug };

class Logger : public ostringstream {
public:
   Logger( LogLevel lv ) : logLevel( lv ) {};
   ~Logger() override {
      cout << LevelNames[static_cast<int>( logLevel )] << ':' << str() << '\n';
   };

   LogLevel logLevel;
};

template <typename T>
inline Logger& operator<<( Logger& lg, const T& body ) {

   if ( lg.logLevel >= sysLogLevel )
      static_cast<std::ostream&>( lg ) << body;

   return lg;
};

但是如果<相关的代码

using StrStrMap = map<string, string>;
inline ostream& operator<<( ostream& os, const StrStrMap& ssm ) {
   os << '{';
   for ( const auto& [k,v] : ssm )
      os << k << ':' << v << ',';
   os << '}';
   return os;
};

using StrStrUoMap = unordered_map<string, string>;
inline ostream& operator<<( ostream& os, const StrStrUoMap& ssm ) {
   os << '{';
   for ( const auto& [k,v] : ssm )
      os << k << ':' << v << ',';
   os << '}';
   return os;
};

int main() {
   StrStrMap ssm1 { { "Flower", "Red" }, { "Grass", "Green" } };
   cout << ssm1 << endl;                        // OK!
   Logger(LogLevel::Infor) << ssm1; // Compilation Error!

   StrStrUoMap ssum1 { { "Flower", "Red" }, { "Grass", "Green" } };
   cout << ssum1 << endl;                          // OK!
   Logger(LogLevel::Infor) << ssum1;   // Compilation Error!
};

情况正确,如果要写入记录器的值是简单类型,例如int,std :: string,c-string等。即使使用模板类的实例,也可以正常进行。我尝试了如下:

template<typename T>
class MyIntTemplate {
public:
   MyIntTemplate( T p ) : payLoad(p) {};
   T payLoad;
};
using MyInt = MyIntTemplate<int>;

inline ostream& operator<<( ostream& os, const MyInt& mi ) {
   os << mi.payLoad;
   return os;
};

using StrVec = vector<string>;
inline ostream& operator<<( ostream& os, const StrVec& sv ) {
   os << '{';
   for ( const auto& v : sv )
      os << v << ',';
   os << '}';
   return os;
};

int main() {
   Logger(LogLevel::Warnn) << 456;                                             // OK!
   Logger(LogLevel::Debug) << "a Debugging Log";             // OK!
   Logger(LogLevel::Infor) << string( "a Informing Log" );  // OK!

   StrVec sv1 { "Flower", "Grass" };
   cout << sv1 << endl;                                        // OK!

   Logger(LogLevel::Infor) << MyInt(123);  // OK!

   return EXIT_SUCCESS;
};

如您所见,std :: cout也是std :: ostream的后代,但是它很好地接受std :: map的实例。我错过了什么?

GCC的错误消息是:

/ usr / include / c ++ / 8 / ostream:656:11:错误:operator<<不匹配(操作数类型为std::basic_ostream<char>const std::unordered_map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >

c++ operator-overloading iostream unordered-map stdmap
1个回答
0
投票

这不是答案,是一个最小的可复制示例:

#include <iomanip>
#include <iostream>
#include <map>
#include <ostream>
#include <sstream>
#include <string_view>
#include <vector>
#include <unordered_map>

using namespace std;

enum class LogLevel {
   Debug, Infor, Notif, Warnn, Error, Fatal
};

constexpr string_view LevelNames[] { "Debug", "Infor", "Notif", "Warnn", "Error", "Fatal" };

LogLevel sysLogLevel { LogLevel::Debug };

class Logger : public ostringstream {
public:
   Logger( LogLevel lv ) : logLevel( lv ) {};

   ~Logger() override {
      cout << LevelNames[static_cast<int>( logLevel )] << ':' << str() << '\n';
   };

   LogLevel logLevel;
};

template <typename T>
inline Logger& operator<<( Logger& lg, const T& body ) {

   if ( lg.logLevel >= sysLogLevel )
      static_cast<std::ostream&>( lg ) << body;

   return lg;
};

using StrStrUoMap = unordered_map<string, string>;
inline ostream& operator<<( ostream& os, const StrStrUoMap& ssm ) {
   os << '{';

   for ( const auto& [k,v] : ssm )
      os << k << ':' << v << ',';

   os << '}';

   return os;
};

int main() {
   StrStrUoMap ssum1 { { "Flower", "Red" }, { "Grass", "Green" } };
   Logger(LogLevel::Infor) << ssum1;

   return EXIT_SUCCESS;
};
© www.soinside.com 2019 - 2024. All rights reserved.