jpereira
jpereira

Reputation: 251

Overload operator<< from function return

I am trying to develop a simple logger.

I have a function with the following prototype:

class Logger{
public:
    std::unique_ptr<MyStream> & getLogger(string, string);
}

and i want to do something like

logger = Logger();
logger.log("INF", "HGH") << "My message" << endl;

for this i overloaded the operator<<

template<typename T>
inline friend std::unique_ptr<MyStream> &operator<<(std::unique_ptr<MyStream>&os, const T&val){
    *os << val;
    return os;
}
inline friend std::unique_ptr<MyStream>& operator<<(std::unique_ptr<MyStream>&os, std::ostream&(*f)(std::ostream&) ){
    *os << f;
    return os;
}

But when i try to do

auto infLogger = log.log(M_LOG_NRM, M_LOG_INF);
infLogger<< "Testing new functionality" << std::endl;

Everything works fine but when i do:

log.log("MOD1", M_LOG_NRM, M_LOG_INF) << "Testing new functionality" << std::endl;

I have this nice compilation error:

cannot convert ‘jpCppLibs::Logger::log(int, int)(std::basic_string<char>(((const char*)"MOD1"), (*(const std::allocator<char>*)(& std::allocator<char>()))), 3, 3)’ (type ‘std::unique_ptr<jpCppLibs::MyStream>’) to type ‘std::unique_ptr<jpCppLibs::MyStream>&’
   log.log(M_LOG_NRM, M_LOG_INF) << "Testing new functionality" << std::endl;

Any help?

The class was working passing by parameter the message and the format+variables, just trying to improve it a little bit

Upvotes: 0

Views: 64

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

template<typename T>
inline friend std::unique_ptr<MyStream> const&operator<<(std::unique_ptr<MyStream> const&os, const T&val){
  *os << val;
  return os;
}

note that a std::unique_ptr<MyStream> const& and std::unique_ptr<MyStream const>& are different types. The first is a reference to a immutable smart pointer to mutable data, the second is a reference to a mutable smart pointer to immutable data.

Temporary objects cannot bind to non-const lvalue references, as protection against implicit conversions leading to changes being discarded silently. However, you do not need a non-const lvalue reference, so there is no problem.

Upvotes: 1

James Kanze
James Kanze

Reputation: 153909

Because you're trying to initialize a non-const reference with a temporary, and that's not allowed.

The usual solution for this problem is to write a small class (which may contain nothing more than your std::unique_ptr), with a template member operator<<; the rules allow member functions to be called on temporaries.

Upvotes: 1

Related Questions