Is there a standard way to convert a class to a string - c++

In Java, the standard is to define the method toString() to return a string representation of a class. Other than overloading operator<<, is there any such standard in C++? I know there are the std::to_string() methods to get a string representation of a number. Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class, or is there a common practice followed by C++ programmers?

The standard way to do this kind of thing is to provide an insertion operator so that an object can be inserted into a stream -- which may be any kind of stream, such as a stringstream.
If you wish, you can also provide a method that converts to a string (useful for your insertion operator), and, if you find the conversion acceptable, you can provide a 'to string' operator.
Here's my standard 'point' class example:
template <typename T>
struct point
{
T x;
T y;
point(): x(), y() { }
point( T x, T y ): x(x), y(y) { }
};
template <typename T>
std::ostream& operator << ( std::ostream& outs, const point <T> & p )
{
return outs << "(" << p.x << "," << p.y << ")";
}
I also tend to keep a handy function around to convert things to strings:
template <typename T>
std::string to_string( const T& value )
{
std::ostringstream ss;
ss << value;
return ss.str();
}
Now I can use it easily:
int main()
{
point p (2,-7);
std::cout << "I have a point at " << p << ".\n";
my_fn_which_takes_a_string( to_string(p) );
You'll find that the Boost Lexical Cast Library is also designed for this kind of thing.
Hope this helps.

The C++ standard does not prescribe a way to do this but it looks like there is a proposal which may introduce such an option Generic to_string/to_wstring functions which says in the motivation section which also highlights the current common practices being taken(which I demonstrate below):
For a long time C++ programmers have been looking for an easy way to
convert an object into its string representation. A typical answer to
this problem was to create a local ostringstream, insert the object
into the stream, and then obtain the resulting string with the str
member function. This solution is simple, safe, flexible and
extensible, though definitely too verbose for something that rather
ought to be a single function call. C++11 provided (a partial)
solution in the form of a set of overloaded to_string/to_wstring
functions. Unfortunately, these are limited only to the built-in
numeric types. Non-standard solutions exist too – most notably
boost::lexical_cast, which offers two-way conversion of objects and
strings, but lacks any formatting control.
This paper proposes a solution that:
generalizes the existing to_string/to_wstring functions for any type that provides a stream output operator and for any basic_string
specialisation,
remains consistent and mostly compatible with these functions,
provides extra formatting and concatenation capabilities,
is conceptually simple by building upon the familiar ostringstream solution.
There are two trip reports STL's and Herb Sutter's and I don't see this paper mentioned in either. So hopefully this will be covered in the post-Kona mailing when it comes out.
The first method they mentioned in the proposal would look something like the example in this answer:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
combined with the something similar to the example from here:
template <typename T>
std::string to_string(const T& value) {
std::ostringstream os;
os << value;
return os.str();
}
We can find a boost::lexical_cast example in the question Enabling Classes for Use with boost::lexical_cast.

Looks like there is no standard way. As I understand C++ standard does not permit overloading of std::to_string function.
I ended up using one of these two solutions:
Solution #1
Instead of toString() method you can use:
operator std::string() const {
return "Object string.";
}
And to support streams you can add something like this:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
return out << static_cast<std::string>(obj);
}
I hope that the << operator will just inline the conversion from the first operator.
Solution #2
Or you can go other way if you think often in the stream-style:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
out << "Object ";
out << "string.";
return out;
}
And use it inside conversion operator:
operator std::string() const {
std::ostringstream out;
out << *this;
return out.str();
}
Either way this get you covered for most of the cases.

Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class,
No.
or is there a common practice followed by C++ programmers.
No. However, I suspect every project has similar functionality. The name and return type most likely depend on the coding guidelines of a project.
At my work, we use
virtual QString toString() const = 0;
in one of our base classes.
You can start using something similar for your project.
virtual std::string toString() const = 0;
in your base class(es).

Related

Best practices on making c++ class "Showable" (string, ostream)

I have a value-semantic class that I'd like to be "showable" in the same sense as Haskells Show class, or Python provides a universal __str__() function.
In c++:
I could overload operator<<(ostream&, ...) so I can output my class to e.g. cout
I could overload operator std::string() so my class converts to std::string
I could overload operator const char*() so my class converts to const char *.
I could write a str() member, or a to_string(...) free function
Each of these functions could be defined in terms of the other. Is one option better over the others? Are these all the options? What would the most elegant way be to do this given c++11/14/17?
The question is going to be put in hold in a very few minutes, but I will still share my thoughts here.
First, of all, we can remove const char* / std::string() operator overloads from the list. If the class is not a string, it should not be convertible to string, and serialization enablement does not make your class a string.
As for str(), to_string and operator << they a pretty equivalent. However, since for any complex class to_string() and str() are very likely to use ostreams internally, I believe, operator << is the best option.
I don't know whether it's best practice or not but...
for debugging I always define operator<< which gives a summarised output in text form (this means it's easy to stream objects to log files)
for formatted output I would probably choose to implement this in terms of free functions: detail::x_detail_writer write_details(const X&) and then give detail::x_detail_writer (which is a functor) an operator<< overload
for anything but the most trivial object I implement to_string in terms of operator<< if at all.
for aiding with debugging output we have a helper class which goes something like this:
template<class T>
struct make_writeable {
friend std::ostream& operator<<(std::ostream& os, const T& t) {
// example prefix...
os << demangle(typeid(T).name()) << "{";
t.write(os);
// example postfix:
os << " }";
return os;
}
};
then derive some class from this and give it a member function called write:
struct X : make_writeable<X>
{
void write(std::ostream& os) const {
// write out members here. they will appear within the prefix and postfix
}
};

c++ overloading operator << of ofstream for Report/Logger class

I'm trying to create a report/logger Class in c++.
I want to have in the main an object called Report and apply to this class the operator << to write to file multiple strings just like ofstream does.
So instead of using the following code:
ofstream myfile ("d://example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n" << "Heya!!!" << endl;
myfile.close();
}
I would like to have something like the following :
Report rLogger ("d://example.txt"); // Report C'tor (const string& s)
logger << "This is a line.\n" << "Heya!!!" << endl;
// the destructor of rLogger will close the file when it dies...
I just can't find out a way to write the operator << as a member function which seems exactly what I need here. The only way I can use the operator << is as friend which isn't helpful in this case. Can someone give me an idea how can I implement it as above?
Thank in advance,
Guy
Try the following:
class Report {
public:
Report() {}
Report(std::string _str) : stream(_str) {}
Report& operator <<(std::string str) {
if (stream.is_open())
stream << str;
return *this;
}
~Report() { stream.close(); }
std::ofstream stream;
};
For the above you must also include the <string> header.
It seems you want to create a stream-like type. Do not create a stream like type by overloading the output operator <<! The way to create a new stream-like type is to create a stream buffer (i.e., a type derived from std::streambuf) and use this to initialize an std::ostream object, probably by using std::ostream as a base class.
The other approaches for overloading operator<<() won't work for manipulators like std::endl: the manipulator std::endl is a function template and for deducing it template arguments when being used it is necessary to have an overload which can be used to deduce the type correct. The std::ostream class does this by providing suitable special overloads.
I realize that this isn't answering your question about how to overload operator<<() as a member but I think it is the wrong approach and it will probably yield better results changing the way the problem is addressed. I would provide more detail on how to create the corresponding classes but there isn't sufficient context given.
It seems like your problems stem from needing to insert different types to your report, such as "Heya!!!" or std::endl.
One flexible solution is to do this with templates.
You may implement it as a member function, where the Report is pointed to by this:
class Report {
public:
template < typename T >
Report& operator <<( const T &data ) { ... }
};
Or as a friend function, where there is no this and Report is instead explicitly mentioned and named:
class Report {
public:
template < typename T >
friend Report& operator <<( Report &r, const T &data ) { ... }
};
Or as a stand-alone function, if the Report has enough public methods to do the job.
template < typename T >
Report& operator <<( Report &r, const T &data ) { ... }
To implement it as a member function and be able to concatenate several streams you just have to return a reference to the object at the end of the function, e.g.:
class Report {
public:
// ...
Report& operator<<(const char *text) {
// write text to file...
return *this;
}
};
Here is a very simple example that prints to standard output instead of a file: http://codepad.org/S8QeJZ1x
If all you want is to make sure the file is closed after use, class Report is unnecessary. std::ofstream's destructor already closes its file.
The other answers so far, which try to define a templated operator<< have a problem: They won't work with some manipulators including std::endl, since it's actually a function template, and the compiler can't figure out what sort of instantiation it should use.
If the purpose of class Report is to add or modify something in the data going through, that's more easily and more correctly done by defining your own streambuf. This article by James Kanze describes how to do that.

Purpose of overloading operators in C++?

What is the main purpose of overloading operators in C++?
In the code below, << and >> are overloaded; what is the advantage to doing so?
#include <iostream>
#include <string>
using namespace std;
class book {
string name,gvari;
double cost;
int year;
public:
book(){};
book(string a, string b, double c, int d) { a=name;b=gvari;c=cost;d=year; }
~book() {}
double setprice(double a) { return a=cost; }
friend ostream& operator <<(ostream& , book&);
void printbook(){
cout<<"wignis saxeli "<<name<<endl;
cout<<"wignis avtori "<<gvari<<endl;
cout<<"girebuleba "<<cost<<endl;
cout<<"weli "<<year<<endl;
}
};
ostream& operator <<(ostream& out, book& a){
out<<"wignis saxeli "<<a.name<<endl;
out<<"wignis avtori "<<a.gvari<<endl;
out<<"girebuleba "<<a.cost<<endl;
out<<"weli "<<a.year<<endl;
return out;
}
class library_card : public book {
string nomeri;
int raod;
public:
library_card(){};
library_card( string a, int b){a=nomeri;b=raod;}
~library_card() {};
void printcard(){
cout<<"katalogis nomeri "<<nomeri<<endl;
cout<<"gacemis raodenoba "<<raod<<endl;
}
friend ostream& operator <<(ostream& , library_card&);
};
ostream& operator <<(ostream& out, library_card& b) {
out<<"katalogis nomeri "<<b.nomeri<<endl;
out<<"gacemis raodenoba "<<b.raod<<endl;
return out;
}
int main() {
book A("robizon kruno","giorgi",15,1992);
library_card B("910CPP",123);
A.printbook();
B.printbook();
A.setprice(15);
B.printbook();
system("pause");
return 0;
}
It doesn't ever have to be used; it's just a convenience, a way of letting user-defined types act more like built-in types.
For example, if you overload operator<<, you can stream books the same way as integers and strings:
cout << "Book #" << n << " is " << books[n] << endl;
If you don't, you'd have to write the same thing like this:
cout << "Book #" << n << " is ";
books[n].printbook();
cout << endl;
Similarly, if you create a Fraction class and give it an operator+, you can use fractions the same way you use integers, and so on.
It's sometimes a tough design choice whether your class should act like a native type in one way or another (for example, does string's operator+ make sense?), but the point is that C++ gives you the choice.
Overloading the << operator allows your objects to be written out to the output in a way you specify, when passed to cout.
Otherwise, cout would just write out the address to your object.
The purpose of overloading operators is mostly syntactic sugar. It makes ugly stuff look nice.
But it's also about unifying interfaces, and an important reason for unifying interfaces is polymoprphism, in this case especially with templates.
Imagine we have a lovely complex number class Complex, and we want to have a Taylor series approximation of sine that we want to make work for Complex and double types.
If we support operator overloading on *, =, / etc. then we can write it like this:
template<typename T>
T sin(T t)
{
T t2 = t*t;
return t*(1 - t2/6 + (t2*t2)/120 );
}
If we cant have overloading on *, / etc. then it starts to get ugly, as we need a helper class to unify the interface for doubles and Complex, heres what it might look like. (I'm still allowing overloading of operator=, otherwise it gets even worse).
template<typename T>
T sin(T t)
{
T t2 = helper<T>::mult( t, t );
T t4 = helper<T>::mult( t2, t2 );
T s(1);
helper<T>::sincrement( &s, -1./6, t2);
helper<T>::sincrement( &s, -1./120, t4);
return helper<T>::mult( t, s );
}
template<>
struct helper<double>
{
static double mult( double a, double b) { return a*b; }
static void sincrement( double * v, double s, double x) { *v += s*x; }
}
template<>
struct helper<Complex>
{
static Complex mult( Complex a, Complex b ) { return a.mult(b); }
static void sincrement( Complex * v, double s, Complex x ) { v->add( x.scale(s) ); }
}
Now I know operator overloading can be ugly, and can hide what's really happening, but used correctly I think that it makes cases like this much easier to understand.
Overloading operators allows a special case of polymorphism.
The best example I can think of is a string class with the + operator overloaded.
In this case the operator would be overloaded to concatenate strings instead of "adding" two strings which doesn't make any sense.
To answer your question specifically overloading operators can (in some cases) produce more readable and maintainable code. However, what "makes sense" for one person may not make sense for the person maintaining the code.
You could easily use a member function instead, it just provides a "syntactic sugar" in most cases. For example in some languages adding 2 strings does a concat.
stringOne = stringOne + stringTwo;
Though it could easily be implemented with a member function like
stringOne.concat(stringTwo);
With an overloaded operator, you can use standard library algorithms which require that operator to be overloaded.
For example:
struct wtf{ wtf(int omg): omg(omg){} int omg; };
wtf operator+ (wtf const &omg, wtf const &lol)
{
return wtf(omg.omg+ lol.omg);
}
#include <iostream>
#include <numeric>
int main()
{
wtf lol[3]= { wtf(1), wtf(2), wtf(3) };
std::cout<< std::accumulate(lol, lol+ 3, wtf(0)).omg;
}
6
The thing about C++ is it passes objects by value, as a fundamental aim of how it works, and this really greatly changes how objects work compared to reference-semantics oriented languages like Java and Objective-C.
Whereas in one of those languages there is a clear distinction between primitive types and objects in terms of how you use them - that is, you copy primitives a lot, you stick them into expressions involving operators, that sort of thing, whereas your interaction with objects is mainly instantiating them, calling methods on them and passing the references to them into functions - in C++ you can use objects pretty much the same way as you use primitives. This brings up a lot of complicated issues that C++ programmers have to deal with, like object lifetimes, whether an object is an lvalue or rvalue (that is, if it has a lifetime outside the expression it appears in), etc.
One thing your question brings up is why a class would overload << and >>. The C++ standard library uses this convention for iostream classes, and highlights another big difference from reference-semantics based languages - in a value-semantics oriented language, class inheritance is inadequate to fully describe what you want to do with an object. We can loosely say that if an object overloads << and >> to stream data in and out of some resource, then it satisfies the concept of an iostream, even if it doesn't inherit from iostream, or ios_base, or something. The meaning of this is twofold:
If you put a value of this type into an expression and used <<, it would behave as expected.
If you instantiate a template with this type as a parameter, which calls operator<< on the object, the code will compile successfully.
I deliberately used the word concept above because there was going to be a feature in C++11 (it got postponed to the next version) called Concepts which would formalise this idea in the language. The situation we have now is a sort of duck typing - if a template wants to use a certain operator with a type, it will compile if the type provides that operator and won't if it doesn't, regardless of what the operator actually means. operator<< is a case in point - in its original meaning, for an integer type, it means "leftward signed bit-shift", but when you are using the concept of iostream, it means "stream data from the object on the right into the object to the left".
Your main purpose overloading the << and >> operators is to create an API in the spirit of the C++ standard library, so it becomes more natural for experienced C++ programmers to use your types.
It's so this way that the operators << and >> are known as insertion/extraction operators when used with the STL streams. From C they were just bit shift operators.
Since in the realm of standard C++ they acquired that meaning and even received new nomenclatures for that, It's aways good to reuse already established programming jargon.
Now, originally in the C++ creation, why it has gone this way for stream operations? by getting the shift operators and labeling them as insertion and extraction operators, I don't know, maybe a matter of taste to better express the idea of insertion/extraction given the appearance of the shift operators, a meaning which now, has become standard and suits to be reused.

Encapsulate a simple type using C++ templates

I'm looking to add functionality to all the simple types in C++.
I want to write a single templated class that takes as a template parameter the type to be encapsulated and then has all the operators defined so that the encapsulated class works exactly as the simple type it encapsulates.
Something like this:
template <typename _SimpleType_>
class Attribute
{
public:
Attribute(_SimpleType_ value){ m_value = value; }
~Attribute(){}
// Cast
operator _SimpleType_() { return(m_value); }
// Comparisons
bool operator==(const a& other) const { return a == m_value; }
etc...
private:
_SimpleType_ m_value;
}
// Use like:
Attribute<int> i = 20;
while(i)
{
if((i & 0xF) == 0)
{
i >>= 2;
}
i--;
} etc...
The question is I'm sure there are a load of nuances that have to be dealt with and specialised template operators written; so is there anywhere that this has already been done so that I can just use that instead?
Boost is too large and complicated to put in my project but I can look at it for pointers if there is a class like this in there - whats its name if there is?
It's pretty simple, if tedious, - you just have to implement all the operators supported by the standard types and where the cast operator is not sufficient.
I have to ask though, why on earth are you trying to do this?
Here is an example of doing with an automatic typecast to T& (tested with GNU C++ 4.3.2):
#include <iostream>
using namespace std;
template <typename T>
class Attribute {
public:
Attribute(const T &value) { v = value; }
operator T & () { return v; }
private:
T v;
};
int main(int argc, char **argv)
{
Attribute<int> i(0);
i = 3;
i++;
i += 4;
i = i + 5;
i <<= 3;
cout << "i is now " << i << endl;
}
The C++ compiler casts automagically the reference to 'Attribute' to a reference to 'int' using the coercion operator 'operator T & ()'. So when the Attribute class does not provide the '++' operator or anything, the object is typecasted to int & and then the operator is looked up from there. Feel free to experiment.
You can get the implementation of the nonmutating operators for free, just by the conversion to _Simple_type_ (and you would get the assignments and increment/decrement by conversion to _Simple_type_&). Another question is whether this is really a good idea, as it creates conversions both T to Attribute<T> and Attribute<T> to T which causes problems while overloading - but you could fix that by making the constructor of Attribute<T> explicit.
This leaves the assignments and increment/decrement - you would just have to implement those.
Another possibility is using boost::operators - a header only library that facilitates creation of operator overloads based on algebraic rules. eg. you create operator+=, and it will provide you operator+. You create operator< and operator== and it will give you the other relationals etc.
Not to do with your question, but you should be aware that names such as _SimpleType_ (that is, names that begin with an underscore and an uppercase character) are reserved for the C++ compiler and Standard Libarary implementors to use - you are not allowed to use them in your own code.
I'm not sure if boost::ref is what you're looking for.
At any rate, the best thing you'd do is to just write it out by hand -- but this will start becoming a problem if you intend to support pointer and reference semantics.
What you'd also proabably need to do is put it in a namespace and implement the free function operator overloads and rely on ADL for it to get picked up. This will get a little unwieldy though as you implement more and more operators.
I like this form of encapsulation of simple types (original author - Sektor van Skijlen):
template<typename T>
class explicit_t
{
private:
T value;
template<typename V> explicit_t(V t);
public:
operator T&() {return value;}
explicit_t(const T& c) : value(c) {}
};
And the short example:
void fun(explicit_t<int> foo) {}
int main()
{
// fun('a');
// fun(3u);
// fun(3.0);
fun(4);
}
So what do I get? No more unwanted conversions.
You might also want to have a look at something more fancy - typegen.

non-member non-friend function syntax

Is their a way to use a non-member non-friend function on an object using the same "dot" notation as member functions?
Can I pull a (any) member out of a class, and have users use it in the same way they always have?
Longer Explanation:
Scott Meyers, Herb Sutter, et all, argue that non-member non-friend functions are a part of an object's interface, and can improve encapsulation. I agree with them.
However, after recently reading this article: http://www.gotw.ca/gotw/084.htm I find myself questioning the syntax implications.
In that article, Herb proposes having a single insert, erase, and replace member, and several non-member non-friend functions of the same name.
Does this mean, as I think it does, that Herb thinks some functions should be used with the dot notation, and others as a global function?
std::string s("foobar");
s.insert( ... ); /* One like this */
insert( s , ...); /* Others like this */
Edit:
Thanks everyone for your very useful answers, however, I think the point of my question has been overlooked.
I specifically did not mention the specific case of operators, and how they retain the "natural" notation. Nor that you should wrap everything in a namespace. These things are written in the article I linked to.
The question itself was:
In the article, Herb suggests that one insert() method be a member, while the rest are non-member non-friend functions.
This implies that to use one form of insert() you have to use dot notation, while for the others, you do not.
Is it just me, or does that sound crazy?
I have a hunch that perhaps you can use a single syntax. (Im thinking how Boost::function can take a *this parameter for mem_fun).
Yes, it means that part of the interface of an object is composed of non member functions.
And you're right about the fact it involves the use of the following notation, for an object of class T:
void T::doSomething(int value) ; // method
void doSomething(T & t, int value) ; // non-member non-friend function
If you want the doSomething function/method return void, and have an int parameter called "value".
But two things are worth mentioning.
The first is that the functions part of the interface of a class should be in the same namespace. This is yet another reason (if another reason was needed) to use namespaces, if only to "put together" an object and the functions that are part of its interface.
The good part is that it promotes good encapsulation. But bad part is that it uses a function-like notation I, personally, dislike a lot.
The second is that operators are not subject to this limitation. For example, the += operator for a class T can be written two ways:
T & operator += (T & lhs, const T & rhs) ;
{
// do something like lhs.value += rhs.value
return lhs ;
}
T & T::operator += (const T & rhs) ;
{
// do something like this->value += rhs.value
return *this ;
}
But both notations are used as:
void doSomething(T & a, T & b)
{
a += b ;
}
which is, from an aesthetic viewpoint, quite better than the function-like notation.
Now, it would be a very cool syntactic sugar to be able to write a function from the same interface, and still be able to call it through the "." notation, like in C#, as mentioned by michalmocny.
Edit: Some examples
Let's say I want, for whatever reason, to create two "Integer-like" classes.
The first will be IntegerMethod:
class IntegerMethod
{
public :
IntegerMethod(const int p_iValue) : m_iValue(p_iValue) {}
int getValue() const { return this->m_iValue ; }
void setValue(const int p_iValue) { this->m_iValue = p_iValue ; }
IntegerMethod & operator += (const IntegerMethod & rhs)
{
this->m_iValue += rhs.getValue() ;
return *this ;
}
IntegerMethod operator + (const IntegerMethod & rhs) const
{
return IntegerMethod (this->m_iValue + rhs.getValue()) ;
}
std::string toString() const
{
std::stringstream oStr ;
oStr << this->m_iValue ;
return oStr.str() ;
}
private :
int m_iValue ;
} ;
This class has 6 methods which can acess its internals.
The second is IntegerFunction:
class IntegerFunction
{
public :
IntegerFunction(const int p_iValue) : m_iValue(p_iValue) {}
int getValue() const { return this->m_iValue ; }
void setValue(const int p_iValue) { this->m_iValue = p_iValue ; }
private :
int m_iValue ;
} ;
IntegerFunction & operator += (IntegerFunction & lhs, const IntegerFunction & rhs)
{
lhs.setValue(lhs.getValue() + rhs.getValue()) ;
return lhs ;
}
IntegerFunction operator + (const IntegerFunction & lhs, const IntegerFunction & rhs)
{
return IntegerFunction(lhs.getValue() + rhs.getValue()) ;
}
std::string toString(const IntegerFunction & p_oInteger)
{
std::stringstream oStr ;
oStr << p_oInteger.getValue() ;
return oStr.str() ;
}
It has only 3 methods, and such, reduces the quantity of code that can access its internals. It has 3 non-member non-friend functions.
The two classes can be used as:
void doSomething()
{
{
IntegerMethod iMethod(25) ;
iMethod += 35 ;
std::cout << "iMethod : " << iMethod.toString() << std::endl ;
IntegerMethod result(0), lhs(10), rhs(20) ;
result = lhs + 20 ;
// result = 10 + rhs ; // WON'T COMPILE
result = 10 + 20 ;
result = lhs + rhs ;
}
{
IntegerFunction iFunction(125) ;
iFunction += 135 ;
std::cout << "iFunction : " << toString(iFunction) << std::endl ;
IntegerFunction result(0), lhs(10), rhs(20) ;
result = lhs + 20 ;
result = 10 + rhs ;
result = 10 + 20 ;
result = lhs + rhs ;
}
}
When we compare the operator use ("+" and "+="), we see that making an operator a member or a non-member has no difference in its apparent use. Still, there are two differences:
the member has access to all its internals. The non-member must use public member methods
From some binary operators, like +, *, it is interesting to have type promotion, because in one case (i.e., the lhs promotion, as seen above), it won't work for a member method.
Now, if we compare the non-operator use ("toString"), we see the member non-operator use is more "natural" for Java-like developers than the non-member function. Despite this unfamiliarity, for C++ it is important to accept that, despite its syntax, the non-member version is better from a OOP viewpoint because it does not have access to the class internals.
As a bonus: If you want to add an operator (resp. a non-operator function) to an object which has none (for example, the GUID structure of <windows.h>), then you can, without needing to modify the structure itself. For the operator, the syntax will be natural, and for the non-operator, well...
Disclaimer: Of course these class are dumb: the set/getValue are almost direct access to its internals. But replace the Integer by a String, as proposed by Herb Sutter in Monoliths "Unstrung", and you'll see a more real-like case.
You can use a single syntax, but perhaps not the one you like. Instead of placing one insert() inside your class scope, you make it a friend of your class. Now you can write
mystring s;
insert(s, "hello");
insert(s, other_s.begin(), other_s.end());
insert(s, 10, '.');
For any non-virtual, public method, it's equivalent to define it as a non-member friend function. If mixed dot/no-dot syntax bothers you then by all means make those methods friend functions instead. There's no difference.
In the future we will also be able to write polymorphic functions like this, so maybe this is the C++ way, rather than artificially trying to force free functions into the dot syntax.
There is no way to write a non member non friend with dot notation, namely because "operator." is not capable of being overloaded.
You should always wrap non member non friend classes in either the anonymous namespace (if only the current translation unit needs the functions) or in some meaningful namespace for users.
However, after recently reading this article: http://www.gotw.ca/gotw/084.htm I find myself questioning the syntax implications.
The syntax implications are something that can be seen everywhere in well-written C++ libraries: C++ uses free functions all over the place. This is unusual for people with a background in OOP but it's best-practice in C++. As an example, consider the STL header <algorithm>.
Using the dot notation thus becomes the exception to the rule, not the other way round.
Notice that other languages choose other methods; this has led to the introduction of “extension methods” in C# and VB that allow to emulate the method-calling syntax for static functions (i.e. exactly what you had in mind). Then again, C# and VB are strictly object-oriented languages so having a single notation for method calls might be more important.
Apart from that, functions always belong in a namespace – although I myself violate this rule occasionally (but only in one compilation unit, namely my equivalent to main.cpp, where this doesn't play a role).
Personally, i like the extensibility of free functions. A size function is an excellent example for this:
// joe writes this container class:
namespace mylib {
class container {
// ... loads of stuff ...
public:
std::size_t size() const {
// do something and return
}
};
std::size_t size(container const& c) {
return c.size();
}
}
// another programmer decides to write another container...
namespace bar {
class container {
// again, lots of stuff...
public:
std::size_t size() const {
// do something and return
}
};
std::size_t size(container const& c) {
return c.size();
}
}
// we want to get the size of arrays too
template<typename T, std::size_t n>
std::size_t size(T (&)[n]) {
return n;
}
Consider now code that uses the free size function:
int main() {
mylib::container c;
std::size_t c_size = size(c);
char data[] = "some string";
std::size_t data_size = size(data);
}
As you see, you can just use size(object) without needing to care about the namespace the type is in (depending on the argument type, the compiler figures out the namespace itself), and without caring what is going on behind the scenes. Consider also uses like begin and end as free function. This is exactly what boost::range does too.
If you want to preserve the dot notation but also separate functions which don't need to be friends out of the class (so they can't access private members thus breaking encapsulation), you could probably write a mixin class. Either make the "regular" insert pure virtual in the mixin, or keep it non-virtual and use CRTP:
template<typename DERIVED, typename T>
struct OtherInsertFunctions {
void insertUpsideDown(T t) {
DERIVED *self = static_cast<DERIVED*>(this);
self->insert(t.turnUpsideDown());
}
void insertBackToFront(T t) // etc.
void insert(T t, Orientation o) // this one is tricksy because it's an
// overload, so requires the 'using' declaration
};
template<typename T>
class MyCollection : public OtherInsertFunctions<MyCollection,T> {
public:
// using declaration, to prevent hiding of base class overloads
using OtherInsertFunctions<MyCollection,T>::insert;
void insert(T t);
// and the rest of the class goes here
};
Something like that, anyway. But as others have said, C++ programmers aren't "supposed" to object to free functions, because you're "supposed" to always be looking for ways to write generic algorithms (like std::sort) rather than adding member functions to particular classes. Making everything consistently a method is more Java-y.
Yes, they should be either global or namespace-scoped.
Non-member non-friend functions look much prettier in C# where they do use dot notation (they are called extension methods).