Is it possible to define a static insertion operator which operates on the static members of a class only? Something like:
class MyClass
{
public:
static std::string msg;
static MyClass& operator<< (const std::string& token) {
msg.append(token);
return *this; // error, static
}
};
alternatively:
static MyClass& operator<< (MyClass&, const std::string &token)
{
MyClass::msg.append(token);
return ?;
}
This is how I would like to use it:
MyClass << "message1" << "message2";
Thank you!
What I would probably do in your situation, is create another class that overloads the operator<<, then make a static member of that type. Like this:
class MyClass
{
public:
static std::string msg;
struct Out {
Out & operator<< (const std::string& token) {
MyClass::msg.append(token);
return *this;
}
};
static Out out;
};
Using it is not quite what you asked for, but close enough I think:
MyClass::out << "message1" << "message2";
If all the members of MyClass are static, it's possible to return a fresh instance.
However, returning a reference poses a problem. There are two solutions:
define a static instance
pass by copy, and not by reference.
The second approach is easiest:
static MyClass operator<< (MyClass, const std::string &token)
{
MyClass::msg.append(token);
return MyClass();
}
The first is one line more:
static MyClass& operator<< (MyClass&, const std::string &token)
{
static MyClass instance;
MyClass::msg.append(token);
return instance;
}
Usage is very close to what you want:
MyClass() << "message1" << "message2";
However, I would not recommend to do this. Why don't you just just use a std::ostringstream? You'll get formatting and some more for free. If you really need global access, declare a global variable.
If you want to use your class as cout, what you can do is example
#include <iostream>
using namespace std;
namespace trace
{
class trace
{
public:
trace& operator<< (const std::string& echo)
{
std::cout << echo << std::endl;
return *this;
}
};
trace t; // Note that we created variable so we could use it.
};
using namespace trace; // Note that we use same namespace so we dont need to do trace::t
int main(int argv, char** argc)
{
t << "Server started..."
<< "To exit press CTRL + Z";
return 0;
}
Output should look like each string in new line like this:
Server started...
To exit press CTRL + Z
You can't. A class-name / type is not a value in itself, you would need an expression like
class Foobar {...};
std::cout << Foobar << std::endl;
so that your static operator<< would be usable, but that is not valid C++. The grammar summary at A.4 shows that putting a type's name there is not valid.
Consider also that operator overloads are just functions with flaky names:
T operator<< (T, T)
^^^^^^^^^^ flaky name, basically same as:
T left_shift (T, T)
And functions in C++ (and most other languages, e.g. C#) can only work on instances of types, not types themselves.
However, C++ offers templates which have type arguments, howhowever, that would not help you to overload functions upon types.
Related
I am overloading operator<< as follows :
std::ostream& operator<<(std::ostream& o, const MyClass& myobj);
Now, I would like to have 2 versions of operator<<, one that would display a short description of my object, and another that would display a longer version.
For example, MyClass could contain information about a client. In the short version I would display just the name, and in the long version I would display more details like birthday, address, etc.
Is there a way to do that in C++ ?
I know I could have a method of MyClass that receives the stream, but it would be called like this :
myObj.DisplayShort(cout)
or
myObj.DisplayLong(cout)
but I would like to stay with a syntax similar to the usual form :
cout << myObj << endl;
The standard way is to create a custom formatting flag and a custom manipulator using std::ios_base::xalloc and std::ios_base::iword.
So you have
class MyClass {
static int fmt_flag_index;
enum fmt_flag { output_short, output_long };
}
You initialize fmt_flag_index somewhere at the program startup:
int MyClass::fmt_flag_index = std::ios_base::xalloc();
Here's your custom formatting flag ready to use. Now IO manipulators can set it:
std::ios_base& myclass_short(std::ios_base& os)
{
os.iword(MyClass::fmt_flag_index) = static_cast<int>(MyClass::output_short);
return os;
}
std::ios_base& myclass_long(std::ios_base& os)
{
os.iword(MyClass::fmt_flag_index) = static_cast<int>(MyClass::output_long);
return os;
}
And operator<< access it:
std::ostream& operator<<(std::ostream& os, MyClass& f)
{
switch (static_cast<MyClass::fmt_flag>(os.iword(MyClass::fmt_flag_index)))
{
case MyClass::output_short: ...;
case MyClass::output_long: ...;
}
}
Use it like this:
MyClass myobj;
std::cout << myclass_long << myobj;
std::cout << myclass_short << myobj;
Demo
I would use a printing adaptor:
class Adaptor
{
MyClass &adaptee;
operator <<
}
And then you can implement different logic based on:
Multiple adapter classes
Single adapter class with a data member
Single adapter class with a template argument
I was exploring an online course on design patterns in C++, and I came across a strange "cast" (?) using an operator function declaration.
The minimal set up is as follows (actual code below):
class A {
...
static B build();
};
class B {
A a;
};
int main()
{
A obj = A::build();
}
Since the build function returns an object of type B, there is a type mismatch and the code fails to compile. To correct this, the instructor defined the following function in class B:
operator A() { return a; }
My question is, how does this work? I understand the mechanism for overloading operators, but in this case we're overloading an actual class, rather than an operator. What is being done when we declare an operator function using another class? What's more, there's no return type defined, does the compiler just assume the return type is the same as the class in which the function is defined? (i.e... B operator A() { ... }) I can't really wrap my head around this concept, intuitively.
I had never heard of this method at all, let alone considered it being possible at all before coming across it just now. I've been trying to research this online, but -understandably, I would say- all my search results return links for basic overloading, or at least more traditional overloading, using operators.
For context, this lecture is on the "Builder" design pattern, using an Html element and an Html builder structure. This is my base code, without modifications yet.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
struct HtmlBuilder;
struct HtmlElement {
std::string name;
std::string text;
std::vector<HtmlElement> elements;
const std::size_t indent_size = 2;
std::string str(const int indent = 0) const {
std::ostringstream oss;
std::string indentation(indent_size * indent, ' ');
oss << indentation << "<" << name << ">\n";
if (!text.empty())
oss << std::string(indent_size * (indent + 1), ' ') << text << '\n';
for (const auto& element : elements)
oss << element.str(indent + 1);
oss << indentation << "</" << name << ">\n";
return oss.str();
}
static HtmlBuilder build(const std::string& rootName);
};
struct HtmlBuilder {
HtmlElement root;
void addChild(const std::string& childName, const std::string& childText) {
HtmlElement childElement { childName, childText };
root.elements.emplace_back(childElement);
}
std::string str() const { return root.str(); }
};
HtmlBuilder HtmlElement::build(const std::string& rootName) {
return { rootName };
}
int main()
{
HtmlBuilder builder { "ul" };
builder.addChild("li", "hello");
builder.addChild("li", "world");
std::cout << builder.str();
}
Output, as expected:
<ul>
<li>
hello
</li>
<li>
world
</li>
</ul>
When demonstrating the "fluent builder" pattern, the instructor had us modify our addChild function to return a reference to the builder structure.
The HtmlBuilder::addChild function is modified as follows: the return type is changed from void to HtmlBuilder& (returning *this)
HtmlBuilder& addChild(const std::string& childName, const std::string& childText) {
HtmlElement childElement { childName, childText };
root.elements.emplace_back(childElement);
return *this;
}
The main function is then rewritten:
int main()
{
auto builder = HtmlElement::build("ul").addChild("li", "hello").addChild("li", "world");
std::cout << builder.str();
}
The output is again:
<ul>
<li>
hello
</li>
<li>
world
</li>
</ul>
Having successfully defined and implemented the fluent builder pattern, the instructor now posed the following question:
How could we get an Html element object from our build function?
My immediate reaction was to think about maybe providing a getter method to the HtmlBuilder class. Something trivial, like this:
struct HtmlBuilder {
...
HtmlElement getElement() const { return root; }
};
You would then "build and get" the element like so:
int main()
{
const auto builder = HtmlElement::build("ul").addChild("li", "hello").addChild("li", "world");
const auto element = builder.getElement();
std::cout << builder.str() << '\n';
std::cout << element.str() << '\n';
}
Both outputs would then be the same. The instructor, however, chose a much different and much more interesting method. Rather than doing it in two steps, via my "build and get" approach, he did the following.
He first rewrote the main function like so (note that he is both building and getting the element in one step, unlike me):
int main()
{
HtmlElement element = HtmlElement::build("ul").addChild("li", "hello").addChild("li", "world");
std::cout << element.str();
}
Initially the compiler rejects this modification because the result of the HtmlElement::build call is an HtmlBuilder object. So to solve this problem, the second thing the instructor did was to define the following function in the HtmlBuilder class:
operator HtmlElement() const { return root; }
Having done this, the code compiles without a hitch and the application output is once again:
<ul>
<li>
hello
</li>
<li>
world
</li>
</ul>
Again, my question is, why or how does this work? What is being done when we declare an operator function using another class? I understand the machinations of the usual operator overloading. It makes intuitive sense to me to overload (), [], or =, but I don't understand how or why this case works. There's not even a declared return type; does the compiler just assume it's meant to return the current class type?
Thank you for your time, everyone.
Re: "we're overloading an actual class". No. operator A() { return a; } is overloading an operator; note the keyword operator. This defines a conversion operator that will be used when the code calls for a conversion from an object of type B to an object of type A.
The use in your example is a bit obscure. Here's an easier example:
B b;
A obj = b;
Creating the obj object requires converting the b object to an object of type A, and that's the job that operator A() does.
In your example, the call to A::build returns an object of type B, so in the code
A obj = A::build();
the call to A::build() returns a temporary object of type B, and the conversion operator (operator A()) converts that object to an object of type A, which is used to initialize obj.
That's a user-defined conversion. The return type is the type after operator, i.e. the destination type. This adds an extra implicit conversion for the type, which is used whenever implicit conversion is considered.
Using the word operator isn't indeed exactly the clearest keyword to use because it doesn't really define an operator (although it can interact with cast operations), but I guess it was to avoid adding another reserved word.
How can I save a pointer to a function without save its return type?
For example:
int GetInt() { return 5; }
string GetStr() { return "abc"; }
FunctionPointerClass GetAny;
int main()
{
GetAny = &GetInt;
auto var = GetAny();
GetAny = &GetStr;
auto var2 = GetAny();
cout << var << '\n' << var2;
}
Edit
A simple way to do this is use variant<> (thanks #sehe), like this:
#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<boost::variant<int, std::string>()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
But, it not too applicable for my project: a non-typed class. To use it, I will need stack all the used return types, to put it in template of variant<>. Like this:
class Var {
private:
void* _val;
template <typename T>
T& _Get() const {
return *((T*)_val);
}
// Static stack variable HERE
public:
val() {}
template <typename T>
val(T val) {
Set(val);
}
~val() {
if(_val != nullptr) delete _val;
}
std::function<boost::variant</*Stack*/>()> Get;
template <typename T>
void Set(T val) {
if(_val != nullptr) delete _val;
_val = new T(val);
Get = &_Get<T>;
// TODO Add 'T' to Stack
}
};
How can I do this?
Not exactly.
You can of course make it a function to print the value.
Or you can use std::variant/boost::variant to return either type.
Other techniques, like Type Erasure might also apply.
I flesh the last two of the approaches here:
Using variant<>
Live On Coliru
#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<boost::variant<int, std::string>()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
Prints
5
abc
Using type erasure
A related technique is type erasure, where you define a "concept" with supported operations (in this case, output streaming) and you hide it behind a polymorphic interface. E.g:
struct Printable {
template <typename T> Printable(T v) : _stored(new concrete<T>(v)) { }
friend std::ostream& operator<<(std::ostream& os, Printable const& p) {
return p._stored->print(os);
}
private:
struct interface {
virtual std::ostream& print(std::ostream& os) const = 0;
virtual ~interface() = default;
};
template <typename T>
struct concrete : interface {
concrete(T v) : v(v) {}
virtual std::ostream& print(std::ostream& os) const override {
return os << v;
}
T v;
};
std::unique_ptr<interface> _stored;
};
In that case you can make the whole program:
Live On Coliru
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<Printable()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
I was going to write this as a comment, and it's not REALLY an answer, but it's a lengthy discussion on the subject of "return different types from the a function with the same name".
C++ doesn't take return type into concideration for overloading functions. In other words, std::string GetAny() and int GetAny() are considered as duplicates of the same function, because they only differ in return type. That's a restriction in the language definition, and you have to work around this restriction by "doing something other than return two different types".
As discussed in another answer, one solution is boost::variant, which is basically a way to define a class that can have multiple different types inside it, which has a type of "tag" to determine what it really contains, and various other clever stuff related to that. Makes it very neat in many ways.
However, it is only really useful for certain classes of problems. In many cases, your code still needs to understand what the data-type is, and having a function that may return a string, an integer or any other "random" data type isn't meaningful. Yes, it's handy to be able to define function pointers that return "any" type - but only in so far as you can have a table of the functions. Your code will not really work well if you do:
std::string s;
s += GetAny(); // Happens to be returning `int` in this call.
Just as bad:
int x = GetAny(); // Returning a string...
So, whilst you can write code that may return "any type", it's hard to make use of such a function without knowing what it returns. I've been programming professionally for over 30 years, and I have used function pointers for many things. So far, I've managed to not need to use this more than a handful times, and every time, it's been some form of solution similar to boost::variant (essentially returning a data-structure, where one field is describing the data-type itself). The two cases I can think of where I have used this are in my Lisp interpreter and my Basic intrepreter. They need a "variable type" that have the ability to hold various types of objects (integer, float, string, list [only in Lisp]). In my Pascal compiler, I do have a proper type system, so it doesn't need to have multiple types returned from a single function (or function pointer). I'd say "it smells funny" when this type of situation happens, and you should probably think about what it is you're trying to solve, and if this is really the right solution.
While trying to work with the << operator and std::basic_ostream, I ran into an error and I don't understand why it's a problem.
In the code samples below, the 1st statement works for both version but the 2nd statement only works with version 1
*TestLog::getInstance() << "Hi this is ";
*TestLog::getInstance() << "Hi this is " << endl;
What exactly happens if we overload the operator << std::basic_ostream?.
Version 1
ofstream logFile("log.txt")
class TestLog : public std::basic_ostream<char, std::char_traits<char> >
{
public:
static TestLog* getInstance()
typedef std::basic_ostream<char,std::char_traits<char> > SuperType;
TestLog& operator<<(SuperType& (*manip)(SuperType& ))
{
stream1_ << manip;
return *this;
}
template<typename T>
TestLog& operator<<(const T& t)
{
stream1_ << t;
return *this;
}
protected:
TestLog();
private:
static TestLog* _instance;
std::ostream& stream1_;
};
TestLog* TestLog::getInstance()
{
if(_instance == 0)
{
_instance = new TestLog();
}
return _instance;
}
TestLog::TestLog():SuperType(logFile.rdbuf()), stream1_(logFile)
{
}
Version 2
class TestLog
{
public:
static TestLog* getInstance()
template<typename T>
TestLog& operator<<(const T& t)
{
stream1_ << t;
return *this;
}
protected:
TestLog();
private:
static TestLog* _instance;
std::ostream& stream1_;
};
TestLog* TestLog::getInstance()
{
if(_instance == 0)
{
_instance = new TestLog();
}
return _instance;
}
TestLog::TestLog():stream1_(logFile)
{
}
The statements as posted all "work" with both approaches shown. I guess you meant to use a manipulator like std::flush (maybe even std::endl which shouldn't be used anyway) instead of "a test" for the second statement as that would, indeed, only work with the first apporoach: std::flush is a function template whose type needs to be deduced upon use. Since your [misguided] implementation of the output operator itself is a template the template arguments for std::flush cannot be deduced and the compilation fails. In the first approach your class contains an explicit overload dealing with the type of a template instantiation of the manipulators which is sufficient to deduce the necessary template argument.
Either way, your approach to creating a new stream is not a good idea at all! Both of your approaches fail, e.g., when trying to pass the resulting "stream" to something which expects and std::ostream& as argument. For output streams there are two independent dimensions which can vary (similarly for input streams):
For any new type objects can be formatted in a specific way. This is done by overloading the shift operator for std::ostream& and the object's type.
The destination of characters can be modified. This is done by inheriting from std::streambuf and overriding the appropriate virtual function, notably overflow().
Your code tries to change the destination of characters by overloading the shift operator. Doing so is not intended to work and does create subtle problems like the problem not working with manipulators, functions taking std::ostream& as argument, or attempts to change the format flags of the "stream" using the various accessor functions.
I want to make a class based on "ostream" that does some auto-formatting to generate comma- or tab-separated-value files. My idea was to override "operator<<" to have it insert a separator before each value (except at the beginning and end of a line), and also to quote strings before writing them. Within the overriding "operator<<" method, I wanted to call the method of the base class, but I can't get it to work right.
Here's an example (compiles with g++ 4.3.3):
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(T value)
{
ostream::operator<<('+');
ostream::operator<<(value);
ostream::operator<<('+');
return *this;
}
};
template<> MyStream& MyStream::operator<< <string>(string value)
{
ostream::operator<<('*');
ostream::write(value.c_str(), value.size()); // ostream::operator<<(value);
ostream::operator<<('*');
return *this;
}
int main()
{
MyStream mystr(cout);
mystr << 10;
cout << endl;
mystr << "foo";
cout << endl;
mystr << string("test");
cout << endl;
return 0;
}
The two "operator<<" methods (template and specialization) are there to handle strings differently than everything else. But:
The characters ('+'/'*') are printed as numbers and not characters.
The C-String "foo" prints as a memory address (I think).
If the "write" line is exchanged with the commented part, the compiler complains that there's "no matching function for call to 'MyStream::operator<<(std::string&)'", even though I thought I was explicitly calling the base class method.
What am I doing wrong? Any help greatly appreciated.
The operator<< overloads that prints strings and characters are free functions. But as you force calling member functions, you will force them to convert to one candidate of the member functions declared in ostream. For '*', it will probably use the int overload, and for "foo", it will probably use the const void* overload.
I would not inherit ostream, but instead store the ostream as a reference member, and then delegate from your operator<< to it. I would also not make operator<< a member, but rather a free function template, and not specialize but overload the operator<< for both std::string and char const*.
Something like the following might work:
include
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(const T& value)
{
(ostream&)*this << '+' << value << '+';
return *this;
}
MyStream& operator<< (const string& value)
{
(ostream&)*this << '*' << value << '*';
return *this;
}
MyStream& operator<< (const char* cstr)
{
(ostream&)*this << '(' << cstr << ')';
return *this;
}
};