I'm trying to create a class like std::cout, however, with colored output. The idea is to call colorstream, but when I overload the operator << gives error.
Codes below:
main.cpp
#include <colorstream/colorstream.hpp>
int main ( int argc, char **argv )
{
cpk::colorstream test;
test << "Hello World";
return 0;
}
colorstream/colorstream.hpp
#include <string>
#ifndef CPK_COLORSTREAM_HPP
#define CPK_COLORSTREAM_HPP
namespace cpk
{
class colorstream
{
public:
colorstream ( ) { };
colorstream operator<<( std::string n );
};
}
#endif // #ifndef CPK_COLORSTREAM_HPP
colorstream/colorstream.cpp
#include <string>
#include <iostream>
/**
* CPK Color Stream Header
*/
#include <colorstream/colorstream.hpp>
cpk::colorstream::colorstream operator<<( std::string n )
{
std::cout << n << std::endl;
}
This is the first time I'm trying to overload operators in, so please help me and if I can explain my mistake.
Thank you, Bruno Alano
#edit
The error:
CMakeFiles/cpk.dir/source/cpk.cpp.o: In function `main':
cpk.cpp:(.text+0x45): undefined reference to `cpk::colorstream::operator<<(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
make[2]: ** [cpk] Erro 1
make[1]: ** [CMakeFiles/cpk.dir/all] Erro 2
make: ** [all] Erro 2
Well, the error is that you're definition of the operator is garbled. It should be
cpk::colorstream cpk::colorstream::operator<< (std::string n)
That said, I strong recommend not to pursue this approach further! To create custom streams you want to derive from std::streambuf and override the relevant operations there (e.g. overflow() and, possibly, xsputn() for output streams).
Actually, if you want to change color e.g. using ANSI Escape Codes you can just create suitable color manipulators and use them with an std::ostream:
#include <iostream>
namespace color
{
std::ostream& red(std::ostream& out) {
return out << "\x1b[31m";
}
std::ostream& reset(std::ostream& out) {
return out << "\x1b[0m";
}
}
int main()
{
std::cout << "hello " << color::red << "world" << color::reset << "\n";
}
On non-UNIX platforms some other mechanism might be necessary, though...
When defining a member operator, what you need to qualify with the class name is the operator name, not the return type.
namespace cpk {
colorstream colorstream::operator<<( std::string n )
{
std::cout << n << std::endl;
}
}
Now, to allow chaining calls to << like you can do with std::cout you need to actually return a value from your operator!
namespace cpk {
colorstream colorstream::operator<<( std::string n )
{
std::cout << n << std::endl;
return *this;
}
}
However, this will return a copy of the stream because it returns by value. That's probably not desirable, so you might be better with returning by reference:
colorstream& colorstream::operator<<( std::string n )
{
std::cout << n << std::endl;
return *this;
}
I need more information on what you are trying to accomplish and what are the errors that are coming up.
I made an assumption with the code provided below that you wanted to output the color to standard out.
I feel that I am completely wrong with this assumption, however here is the code...
main.cpp
#include <colorstream/colorstream.hpp>
int main ( int argc, char **argv )
{
cpk::colorstream test;
test.SetColor("RED");
std::cout << test << std::endl;
return 0;
}
colorstream/colorstream.hpp should be:
#include <iostream>
#include <string>
#ifndef CPK_COLORSTREAM_HPP
#define CPK_COLORSTREAM_HPP
namespace cpk
{
class colorstream
{
public:
std::ostream& operator<< (std::ostream& stream, const cpk::colorstream& cs);
void SetColor(const std::string &color){m_Color = color;}
private:
std::string m_Color;
};
}
#endif // #ifndef CPK_COLORSTREAM_HPP
colorstream/colorstream.cpp should be:
#include <string>
#include <iostream>
/**
* CPK Color Stream Header
*/
#include <colorstream/colorstream.hpp>
std::ostream& operator<<(std::ostream& stream, const cpk::colorstream& cs)
{
stream << cs.m_Color;
return stream;
}
Related
I'm getting an compilation error, related to std::invoke, and also another that can not specialize the template for invoke.
This is the code:
#pragma once
#include <thread>
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
class ThreadLoader {
private:
unsigned int id;
void _loadFile(const std::string& filepath) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Loading " << filepath << "\n";
}
public:
static unsigned int counter;
ThreadLoader() {
id = counter;
counter++;
}
void loadFile(const std::string& filepath) {
std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);
t.join();
}
friend std::ostream& operator<<(std::ostream& os, const ThreadLoader& t) {
return os << t.id << std::endl;
}
};
unsigned int ThreadLoader::counter = 0;
The error appears when I tried to call the loadFile function.
I already checked this. I think followed the accepted answer, however, the error persists. I think that I'm doing something wrong in std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);, but I don't find what is it.
You have your parameters the wrong way round, it should be:
std::thread t(&ThreadLoader::_loadFile, this, std::ref(filepath));
This is my very first question on StackOverflow. I've searched for similar "Identifier not Found" errors but couldn't find anything helpful. I'll be grateful for your help since I've been trying to work this out for 2 hours with no results.
It basically creates an object of type "Addition" and prints "1 + 1 = 2" (if it worked).
When I was not using templates it was working fine. But when I changed everything to templates it stopped working. I couldn't figure this out.
Visual studio does not underline anything in red, however I get a "identifier not defined" error for m_Argument_1 and m_Argument_2.
Thank you for your help and I apologize if this is a too simple question to ask here, but nevertheless I couldn't find a way out or figure out where the problem is.
This is my header file "Expression.h":
#ifndef OPERATION_HEADER
#define OPERATION_HEADER
#include <string>
#include <iostream>
template <typename T>
class Expression
{
protected:
char m_ExpressionSign; /* Represents Expression's Sign ('+','-','*','/') */
T m_Argument_1; /* Represents L Argument */
T m_Argument_2; /* Represents R Argument */
public:
Expression(T arg_1, T arg_2, char expressionSign) : m_Argument_1(arg_1), m_Argument_2(arg_2), m_ExpressionSign(expressionSign) { };
virtual T Result() const = 0;
virtual void Print(std::ostream& out) const;
friend std::ostream& operator << (std::ostream& out, const Expression<T>& expression);
};
template <typename T>
class Addition : public Expression<T>
{
public:
Addition(T arg1, T arg2) : Expression<T>(arg1, arg2, '+') {};
T Result() const { return m_Argument_1 + m_Argument_2; };
};
template <typename T>
void Expression<T>::Print(std::ostream& out) const
{
out << m_Argument_1 << " " << m_ExpressionSign << " " << m_Argument_2 << " = ";
}
template <typename T>
std::ostream& operator << (std::ostream& out, const Expression<T>& expression)
{
expression.Print(out);
return out;
}
#endif /* OPERATION_HEADER */
And this is my main.cpp:
#include <iostream>
#include <iomanip>
#include "Expression.h"
int main(int argc, char** argv)
{
Addition<int> A2(1, 1);
std::cout << "A2: " << A2 << " = " << std::setw(2) << A2.Result() << std::endl;
retun 0;
}
When inheriting from a class template, identifiers need to be qualified so that the compiler knows where they come from. In this case, in the definition of Addition, you could do:
T Result() const { return this->m_Argument_1
+ this->m_Argument_2; };
Alternatively, you could qualify the names like this:
T Result() const { return Expression<T>::m_Argument_1
+ Expression<T>::m_Argument_2; };
I have some trivial logging:
BOOST_LOG_TRIVIAL(trace) << make_trace_record();
Now make_trace_record is a somewhat expensive function to call (don't ask why, it's complicated). I want to call it only if the log currently passes filtering. How can I do that? I don't see a way to call the severity filter explicitly.
Boost.Log filters beforehand; therefore, make_trace_record() will not be called if the severity is not high enough.
In order to set the severity filter for the trivial logger, call:
boost::log::core::get()->set_filter(
boost::log::trivial::severity >= boost::log::trivial::...
);
For instance, the following example outputs 1, showing that expensive() is only called once:
Live On Coliru
#include <iostream>
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>
int count = 0;
int expensive()
{
return ++count;
}
int main()
{
boost::log::core::get()->set_filter(
boost::log::trivial::severity >= boost::log::trivial::warning
);
BOOST_LOG_TRIVIAL(error) << expensive();
BOOST_LOG_TRIVIAL(info) << expensive();
std::cout << count << '\n';
return 0;
}
Prints:
[2018-05-21 14:33:47.327507] [0x00007eff37aa1740] [error] 1
1
For those wondering how it works, take a look to: How does the "lazy evaluation" of Boost Log's trivial loggers work?
Acorn's answer correctly points out that Boost.Log macros already implement conditional execution of the streaming expression. This behavior is documented in the Tutorial.
I will add that you can generate log records manually, avoiding the macros. An example is given here:
logging::record rec = lg.open_record();
if (rec)
{
logging::record_ostream strm(rec);
strm << "Hello, World!";
strm.flush();
lg.push_record(boost::move(rec));
}
This can be useful if log message formatting is complicated and doesn't fit easily in a streaming expression.
I would do this with an intermediate class who's ostream operator lazily calls your function.
Something like this:
#include <type_traits>
#include <utility>
#include <ostream>
#include <iostream>
namespace detail
{
// an ostreamable object that will stream out the result of a unary function object call
template<class F>
struct lazy_generator
{
void write(std::ostream& os) const
{
os << generator_();
}
friend std::ostream& operator<<(std::ostream& os, lazy_generator const& tr)
{
tr.write(os);
return os;
}
F generator_;
};
}
// construct a lazy_generator
template<class F>
auto lazy_trace(F&& f)
{
return detail::lazy_generator<std::decay_t<F>>({std::forward<F>(f)});
}
// test
int main()
{
extern std::string make_trace_record();
// function pointer
std::clog << lazy_trace(&make_trace_record);
// function object
std::clog << lazy_trace([](){ return make_trace_record(); });
}
Update: I made Sergii's changes below, but now I get the error: undefined reference to `cs202::operator<<(std::basic_ostream >&, cs202::Rational const&)'. Any ideas how to fix this? Thanks
I would appreciate help figuring out why I am getting this error:
"error: 'output' is not a member of namespace 'cs202'"
I have a class called Rational as follows:
#ifndef RATIONAL_H
#define RATIONAL_H
namespace cs202{
class Rational
{
private:
int m_numerator;
int m_denominator;
public:
Rational(int nNumerator = 0, int nDenominator = 1) {
m_numerator = nNumerator;
m_denominator = nDenominator;
}
int getNumerator(){return m_numerator;}
int getDenominator(){return m_denominator;}
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational);
};
}
#endif
The implementation file for the friend function which overrides the << operator looks like this:
#include "rational.h"
namespace cs202{
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Finally, Main looks like this:
#include <iostream>
#include "rational.h"
using namespace std;
using namespace cs202;
int main()
{
Rational fraction1(1, 4);
cs202::output << fraction1 << endl;
return 0;
}
I have tried using cout instead of cs202:output, I have tried with and without the namespace cs202 (which is a requirement of the assignment), and I have tried making the operator overload function a member function of the class rather than a friend function to no avail.
What am I missing? Thanks
I suppose you want it out to standard output (to console)
int main()
{
Rational fraction1(1, 4);
std::cout << fraction1 << endl;
return 0;
}
Also you do not need friend here. "Friend" keyword is used only in a class
#include "rational.h"
namespace cs202{
std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Thanks, I figured it out. I had to change the placement of the {} for the namespace.
I am a C++ beginner ( came from Java ). I have the following code:
//#include <boost/algorithm/string.hpp>
#include <iostream>
#include <math.h>
#include <vector>
#include <string.h>
#include <string>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <memory>
#include <assert.h>
#include <cctype>
using namespace std;
class Point{
private:
int x;
int y;
public:
Point(int x,int y){
this->x=x;
this->y=y;
}
int getX(){
return x;
}
int getY(){
return y;
}
operator const char*(){
return toString().c_str();
}
string toString(){
ostringstream stream;
stream<<"( "<<x<<", "<<y<<" )";
return stream.str();
}
};
class Line{
private:
Point p1=Point(0,0);
Point p2=Point(0,0);
public:
Line(Point p1, Point p2){
this->p1=p1;
this->p2=p2;
}
Point getP1(){
return p1;
}
Point getP2(){
return p2;
}
operator const char*(){
ostringstream stream;
stream<<"[ "<<p1<<" -> "<<p2<<" ]";
return stream.str().c_str();
}
// operator const char*(){
// ostringstream stream;
// stream<<"[ "<<p1<<" -> ";
// stream<<p2<<" ]";
// return stream.str().c_str();
// }
};
int main()
{
Line line=Line(Point(1,2), Point(3,4));
cout<<line<<endl;
cout<<"\nProgram exited successfully."<<endl;
return 0;
}
I have redefined the operator const* so that I can use cout<
But, If I run the program as it is now, with the second block commented out ( I have 2 versions of operator const*, and by default the second one is commented out ) ,it will display
[ (1, 2) -> (1, 2) ]
But when running with the second block uncommented, the output is as expected:
[ (1, 2) -> (3, 4) ]
The issue seems to occur when I display both Point objects in the same line ( some kind of chaining, though I don't know if chaining is the right word here )
My question, is,why is this happening?
UPDATE
I have added the std::ostream& operator << function to my Line class but now I'm receiving the following errors:
/home/ryu/qt_workspace/hello/main.cpp:67: error: 'std::ostream& Line::operator<<(std::ostream&, const Line&)' must take exactly one argument
/home/ryu/qt_workspace/hello/main.cpp:77: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
Regards,
Aurelian
If you want to use cout <<, there is a more direct way to do that.
Add this function to Line.
friend std::ostream& operator << ( std::ostream & os, const Line & l ){
os << "[ " << l.p1 << " -> " << l.p2 << " ]";
return os;
}
You should also note that your approach was returning invalid memory - this is a significant way that Java differs from C++.
return stream.str().c_str(); // Danger!
stream was declared in operator const char*() which limits its lifetime to that function. It is destroyed when that scope is exited. As a result, you are returning a pointer to something that no longer exists.
actually I think with C++11 returning the string by value is perfectly fine, so you can do the transfer there instead of using the cstring underneath.
What are move semantics?