Custom Stringstream - Convert std::wstring & std::string - c++

I've got a template class derived from std::basic_stringstream<typename TString::value_type...>, as you can see. The problem happens while trying to convert them. It's probably an obvious problem, though I cannot seem to figure out the solution.
As example in main, I have a simple std::wstring and initialize it with L"123".
After the std::wstring has been constructed, the operator of the custom basic_stringstream class is called (depending on std::wstring or std::string).
Inspecting the WCStringStream object for debugging purposes, shows that it contains - instead of the string L"123", the address of the first element of the entered string. The functions to_bytes and from_bytes do return the correct converted string, so the only problem left is the operator being called in both operator-functions:
*this << std::wstring_convert<...>().xx_bytes(s);
Example:
Template class is std::wstring.
Input is a std::string.
&operator<<(const std::string &s) is being called.
String is converted.
&operator<<(const std::wstring &s) is being called.
String-type matches with template type.
Operator of base-class (basic_stringstream) is called. (Or std::operator...)
Result:
Inspecting: {_Stringbuffer={_Seekhigh=0x007f6808 L"003BF76C췍췍췍췍췍췍췍췍췍...}...}
WCStringStream<std::wstring>::str() -> "003BF76C"
Expected result:
"123"
What's going wrong here ?
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <codecvt>
template<class TString>
class WCStringStream : public std::basic_stringstream<typename TString::value_type,
std::char_traits<typename TString::value_type>,
std::allocator<typename TString::value_type> >
{
typedef typename TString::value_type CharTraits;
typedef std::basic_stringstream<CharTraits, std::char_traits<CharTraits>, std::allocator<CharTraits> > MyStream;
//more typedefs...
public:
//Constructor...
inline WCStringStream(void) { }
inline WCStringStream(const TString &s) : MyStream(s) { }
//and more...
//operator>> overloads...
//defines for VS2010/2015 (C++11) included
inline WCStringStream &operator<<(const std::wstring &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
return *this;
}
inline WCStringStream &operator<<(const std::string &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
return *this;
}
};
//Example main
int main(int argc, char *argv[])
{
typedef std::wstring fstring;
WCStringStream<std::wstring> ws;
WCStringStream<std::string> ss;
ws << fstring(L"123");
int a = 0;
ws >> a;
std::cout << a << std::endl;
ss << fstring(L"123");
int b = 0;
ss >> b;
std::cout << b << std::endl;
return 0;
}
I'm compiling currently in VS2015 but I'd need it to run on VS2010 too.

First off: I think the approach to overload formatting function in a base class is ill-advised and I strongly recommend to not do it! I do realize that any alternative will require a bit more work.
In fact, I think your primary problem is actually that you do not reach your overloaded functions anyway just showing how fragile the approach is (I think the string describe what overload ends up being called but I haven't verified that these are indeed accurate, partly because the code provided in the question is lacking necessary context):
WCStringStream<std::string> stream;
stream << "calls std::operator<< (std::ostream&, char const*)\n";
stream << L"calls std::ostream::operator<< (void const*)\n";
stream << std::string("calls std::operator<< (std::ostream&, T&&)\n";
std::string const s("calls your operator\n");
stream << s;
Since the overloaded output operators for strings and string literals can't be changed and they do the wrong think with respect to code conversions, I recommend using an entirely different approach although it still won't be without peril(*): convert the strings explicitly although using a more nicely packaged version of the code than the standard provides.
Assuming always using char as character type for all uses I would use a function wcvt() which is called for all strings and string-literals when inserting them into a stream. Since at the point the function is being called it wouldn't know the type of the stream it is going to be used with, it would return essentially a reference to the character sequence which is then converted appropriately for the character type used for the stream. That would be something along these lines:
template <typename cT>
class wconvert {
cT const* begin_;
cT const* end_;
public:
wconvert(std::basic_string<cT> const& s)
: begin_(s.data())
, end_(s.data() + s.size()) {
}
wconvert(cT const* s)
: begin_(s)
, end_(s + std::char_traits<cT>::length(s)) {
}
cT const* begin() const { return this->begin_; }
cT const* end() const { return this->end_; }
std::streamsize size() const { return this->end_ - this->begin_; }
};
template <typename cT>
wconvert<cT> wcvt(cT const* s) {
return wconvert<cT>(s);
}
template <typename cT>
wconvert<cT> wcvt(std::basic_string<cT> const& s) {
return wconvert<cT>(s);
}
template <typename cT>
std::basic_ostream<cT>& operator<< (std::basic_ostream<cT>& out,
wconvert<cT> const& cvt) {
return out.write(cvt.begin(), cvt.size());
}
std::ostream& operator<< (std::ostream& out, wconvert<wchar_t> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
std::wostream& operator<< (std::wostream& out, wconvert<char> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
Of course, using this approach requires the use of wcvt(s) whenever s may be a string which needs to be converted. It is easy to forget doing so and it seems the original objective was to not have to remember the use of such a conversion. However, I don't see any alternative which is less fragile with the system of existing streams. Entirely abandoning the use of streams and using an entirely separate system of formatted I/O may yield less fragile approach.
(*) The approach easiest to get right is to stick with just on character type in a program and always using this character type. I do believe it was actually an error to introduce a second character type, wchar_t, and it an even bigger error to further complicate the existing mess by having also introduced char16_t and char32_t. We'd be much better off there were just one character type, char, although it actually wouldn't represent character but bytes of an encoding.

The problem was to explicitly call the base class operator, which takes the const void *_Val overload and prints the address.
MyStream::operator<<(s.c_str());
The solution to the problem:
if (typeid(TString) == typeid(s))
{
MyStream &os = *this;
os << s.c_str();
}
Of course calling *this << s.c_str() results in recursion, but the using the base class, it calls the global overloaded operator for the correct char-type wchar_t / char.
An also working solution is to use the member-function write instead of the operator.

Related

How to generically convert a string to another type using a template function

I have a class containing a string member variable and am trying to write a template function that will allow me to convert the string to another type. As a simplified example, without templates this is what I would do.
struct A {
std::vector<std::string> tokens;
};
void Test(const A& a) {
// Get the final token value as an int, or default to 42.
int i = a.tokens.empty() ? 42 : std::stoi(*a.tokens.rbegin());
}
This however has gotten tedious to write in as many places as I'm trying to get the final token and parse it, so I've written the following to assist.
struct A {
std::vector<std::string> tokens;
const string& GetLast(const string& defaul = "") {
return tokens.empty() ? defaul : *tokens.rbegin();
}
int GetLast(int defaul) {
return tokens.empty() ? defaul : std::stoi(*tokens.rbegin());
}
float GetLast(float defaul) {
return tokens.empty() ? defaul : std::stof(*tokens.rbegin());
}
};
void Test(const A& a) {
int i = a.GetLast(42);
}
This works fine but it just seems to be asking to be made into a template and allow conversion to any sort of type, provided a converter function is provided. I can't seem to find a generic solution that works, however. The following is the closest thing I can think of that should work, but I constantly get compiler errors that the template types can't be deduced.
template <typename T, typename Converter, typename... Args>
T GetLastAs(T defaul, Args ...args)
{
return tokens.empty() ? defaul : Converter(*tokens.rbegin(), args...);
}
with usage a.GetLastAs<float, std::stof>(42.0f)
Is there a generic solution to this problem, or is that just wishful thinking on my part?
Edit:
I've also gotten close with the following implementation:
template<class Converter, typename T, typename ...Args>
T GetLast(T defaul, Args ...args, Converter f = Converter()) const
{
return tokens.empty() ? defaul : f(*tokens.rbegin(), args...);
}
with a converter structure defined as struct ToInt { int operator()(const std::string& str) { return std::stoi(str); } };
and a usage of a.GetLast<ToInt>(42); or a.GetLast(42, ToInt());
But I cannot replace the ToInt in the usage to std::stoi and I believe the reason may be because stoi has an overload to take wstring instead of string and the GetLast method cannot figure out which overload to use. I don't know if it's even possible to specify which overload to use.
You can use a stringstream to extract values of default constructible types like this:
#include <string>
#include <sstream>
#include <iostream>
template <typename T>
T GetAs(const std::string& s) {
std::stringstream ss{s};
T t;
ss >> t;
return t;
}
int main() {
std::string s{"3.5"};
std::cout << GetAs<int>(s) << "\n";
std::cout << GetAs<double>(s) << "\n";
std::cout << GetAs<std::string>(s) << "\n";
}
I put the default and the fact that the string is element of a vector aside, because that isnt essential for the solution.
You could put the string into an std::istringstream and extract the value into a variable using the >> operator.
As in
T value{};
std::istringstream{ string_to_convert } >> value;
Of course, this requires T to be default-constructible, as well as there being an >> operator defined for T.
IIRC this is how Boost lexical cast works (or at least used to work). If you already using Boost in your project, I suggest you use its lexical cast library instead of making your own.
Or for more generic conversion (if you're using Boost) Boost convert. Which can handle different numeric bases.

How to write my own manipulator?

Let's suppose I want to write my own manipulator for input and output.
cin >> mymanip >> str;
or
cout << mymanip << str;
What I want that mymanip does is toggle case the caracters I read from input and assigns the result to one string.
So, if I type "QwErTy" I get "qWeRtY" in the string.
This is a very basic task with one function, but i want to learn more about manipulators.
Can someone give a clue?
Thank you.
All that a manipulator does is set the corresponding bits in the std::ios_base base class.
For example, the std::setprecision() manipulator simply invokes std::ios_base::precision(), on the manipulated stream.
The implementation of std::setprecision() is almost readable, in gcc's headers (a rarity, for a C++ library template implementation):
inline _Setprecision setprecision(int __n)
{ return { __n }; }
std::setprecision() returns an internal std::_Precision object. Then, a simple template overload for the >> (and the << operator, which is similar) operator, for the std::_Precision object, handles the rest of the magic:
template<typename _CharT, typename _Traits>
inline basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
{
__is.precision(__f._M_n);
return __is;
}
In your case, there are no bits in the std::ios_base class that implement your desired input/output transformation. As such, a manipulator, per se, won't work here.
What you're trying to do requires a completely different, more complicated, approach:
A custom subclass of std::[io]stream, that uses a custom subclass of std::streambuf.
The std::streambuf subclass reads or writes from a chained stream, transforming the input or output as you've described.
Reading or writing from the custom subclass ends up reading or writing from the chained stream, transforming the data accordingly.
The way is a little tricky - but it can be done, you can add own manipulator for stream.
First, you need your toggle:
class toggle_t {};
constexpr toggle_t toggle;
Next - the version for ostream (the case for istream is very similar...):
After putting toggle to ostream - you need some special object:
struct toggled_ostream
{
std::ostream& os;
};
inline toggled_ostream operator << (std::ostream& os, toggle_t)
{
return { os };
}
Beware, that someone might put togglein wrong place: cout << toggle << 123 - so it should work for all other types as ordinary stream:
template <typename T>
std::ostream& operator << (toggled_ostream tos, const T& v)
{
return tos.os << v;
}
So - for char types (like char, const char*, std::string) write your toggle overloads. I am giving you version for char - it shouldn't be a problem to write version for "longer" types:
std::ostream& operator << (toggled_ostream tos, char v)
{
char c = std::isupper(v) ? std::tolower(v)
: std::islower(v) ? std::toupper(v) : v;
return tos.os << c;
}
Working demo.
You cannot do that. What you can do instead are manipulators that would take the string as argument, i.e.
std::cout << toggle(str);
std::cin >> toggle(str);
A manipulator is only ever so-called syntactic sugar, i.e. it can do things more conveniently than otherwise. For example,
std::cout << std::setw(5) << x <<;
will do the same as
std::cout.width(5);
std::cout << x;
but is more convenient as it allows to be chained together with other << operations.
Now, there is no formatting support of the thing you want (swap lower and upper case characters), and hence also no way to provide syntactic sugar for that.
However, if the manipulator can take your string as an argument, then of course, you can achieve what you want, implemented in the standard way of manipulator implementation. For example,
struct toggle_output
{ std::string const&str; }
inline toggle_output toggle(std::string const&str)
{ return {str}; }
inline std::ostream& operator<<(std::ostream&out, toggle_output const&t)
{
for(auto c:t.str)
if (std::islower(c)) out<<std::toupper(c);
else if(std::isupper(c)) out<<std::tolower(c);
else out<<c;
return out;
}
struct toggle_input
{ std::string &str; }
inline toggle_input toggle(std::string&str)
{ return {str}; }
inline std::istream& operator>>(std::istream&in, toggle_input &t)
{
in >> t.str;
for(auto&c:t.str)
if (std::islower(c)) c=std::toupper(c);
else if(std::isupper(c)) c=std::tolower(c);
return in;
}
You may also need (to avoid confusion)
inline std::ostream& operator<<(std::ostream&out, toggle_input const&t)
{ return out<<toggle_output(t.str); }
As other answers explain, manipulators simply mimic existing std::ios_base functionality.
There's a simple solution to your problem, though I'm not sure if this can be called a manipulator:
struct toggle_in_helper
{
std::string & res;
};
toggle_in_helper toggle (std::string & res)
{
return {res};
}
std::istream & operator >> (std::istream & in, toggle_in_helper h)
{
in >> h.res;
for (auto & c : h.res)
// toggle the case of 'c'
;
return in;
}
That is, we create a helper class toggle_in_helper with overloaded operator >> which does the job.

Is it possible to have a C++ method accept either const char* and const wchar_t* as a parameter without overloading the method?

UPDATE:
I went for the template approach cause it seemed the most elegant / concise but then I end up with stuff like this:
template<typename charType>
int doSomethingWithString(const charType* buffer)
{
wchar_t* tempBuffer = NULL;
if(typeid(charType) == typeid(char))
{
tempBuffer = (wchar_t*)malloc(sizeof(wchar_t)*strlen((char*)buffer));
mbstowcs(tempBuffer, (const char*)buffer, strlen((const char*)buffer));
}
else if(typeid(charType) == typeid(wchar_t))
{ tempBuffer = (wchar_t*)malloc(sizeof(wchar_t)*strlen((char*)buffer));
tempBuffer = wcscpy(tempBuffer, (const wchar_t*)buffer);
}
At which point I feel it's kind of ugly (specially since I still have to have all those casts there to let the compiler know). I also tried turning the parameter into a wstring but I just don't seem to find an appropriate constructor for both cases?
It's been a while now that I've been away from C++ and I can't remember the C++ way of going about this:
Let's say I have a class with some method myClass::doSomethingWithString(...) and I want the same method to be able to be called passing in a character sequence as either const char* or const wchar_t*. Was there a way to make the method be able to accept both types of "strings" and tell if the parameter is const char* or const wchar_t* inside the method implementation? Or is method overloading the only way to go about it?
Method overloading is the only way to go about it.
Alternately, You could write a single template function.However, in that case the actions you perform inside the function would have to be same in either case. In this case the compiler will generate source code of the functions for your both the types.
Overloading is probably the best way to go about it, unless you're using another API that allows exactly the same syntax with both char* and wchar_t*.
void foo(char const *c) {
std::cout << c << '\n';
}
void foo(wchar_t const *c) {
std::wcout << c << L'\n';
}
You could also use templates. If the code doesn't actually change between char and wchar_t versions then you'll only have one version:
template<typename CharT>
void foo(CharT const *c) {
std::cout << "foo called\n";
}
But since doing anything useful usually involves using the argument, and using the argument usually requires different code (e.g. calling printf for char and wprintf for wchar_t) you'll have to have a version for each type. With a template you'd do that by specializing.
template<typename CharT>
void foo(CharT const *c);
template<> void foo<char>(char const *c) { /* char version */ }
template<> void foo<wchar_t>(wchar_t const *c) { /* wchar_t version */ }
Now, if you have an API that provides an identical interface for wchar_t and char via overloading or specializing, then templates let you build on top of that by having a single version for both types using the overloaded API:
// Given the above overloads/template specializations:
template<typename CharT>
void bar(CharT const *c) {
foo(c); // calls foo(char const *) or foo(wchar_t const *) as needed.
}
But since you're asking if there's a way to tell inside the function what the type is, it seems likely that you want to have different versions. In which case you're probably best off using overloads, or factoring the differences out into overloaded functions so the main function can be a single template.
There is another option that's probably a bad idea. Depending on the actual differences you might be able to have a single template and then do something like:
template<typename T>
int foo(T const *t) {
if(sizeof T == sizeof wchar_t) {
// wchar_t version
} else {
// char version
}
}
And someday C++ may adopt static_if in which case you'll be able to do:
template<typename T>
int foo(T const *t) {
static_if(std::is_same<T,wchar_t>::value) {
// wchar_t version
}
static_if(std::is_same<T,char>::value) {
// char version
}
}
char and wchar_t are different types, so are the pointers to them. Thus you cannot write one function that accepts both as there is no common "parent" (so to speak).
YOu can write a template function that accepts the type as a template parameter. In that case you still have two functionsin your binary program if you call it both with char* and wchar_t*, but in the cose you will see only one function body.
template<T> void someFunction(T* str) {
// your code here. Use T when you would use char or wchar_t in a regular function
}
You can use method overloading. I would also suggest using std::string and std::wstring for C++.
Example:
class MyClass
{
public:
void doSomethingWithString(std::string s)
{
std::cout << "String: " << s << std::endl;
}
void doSomethingWithString(std::wstring ws)
{
std::wcout << L"Wide String: " << ws << std::endl;
}
};
...
MyClass myClass;
myClass.doSomethingWithString("const char *");
myClass.doSomethingWithString(L"const wchar_t *");
Write a class that has implicit constructors for both kinds of arguments:
struct String {
String(const char*): called_with_wchar_t(false) { }
String(const wchar_t*): called_with_wchar_t(true) { }
bool called_with_wchar_t;
};
void function(const String&);
...
function("a");
function(L"a");
Or use Boost.Variant.

Printing to nowhere with ostream [duplicate]

This question already has answers here:
Standard no-op output stream
(6 answers)
Closed 2 years ago.
I'd like to send data to nowhere, I mean that I don't want to print data in console nor in file, but I need some std::ostream object. How to do that?
I've used:
std::ostream bitBucket(0);
recently without problems, although it was flagged as having some potential problems if you looked at it from a certain angle (see the link below).
Aside: From what I understand (and I'm not entirely sure of this), that call above eventually ends up calling basic_ios::init(0) and, because that's a NULL pointer being passed in, it sets the stream state, as returned by the rdstate() function, to the badbit value.
This in turn prevents the stream from outputting any more information, instead just tossing it away.
The following program shows it in action:
#include <iostream>
int main (void) {
std::ostream bitBucket(0);
bitBucket << "Hello, there!" << std::endl;
return 0;
}
The page where I got it from also had this as a probably-cleaner solution (slightly modified to remove the duplication of my first solution above):
#include <iostream>
class null_out_buf : public std::streambuf {
public:
virtual std::streamsize xsputn (const char * s, std::streamsize n) {
return n;
}
virtual int overflow (int c) {
return 1;
}
};
class null_out_stream : public std::ostream {
public:
null_out_stream() : std::ostream (&buf) {}
private:
null_out_buf buf;
};
null_out_stream cnul; // My null stream.
int main (void) {
std::cout << std::boolalpha;
//testing nul
std::cout << "Nul stream before: " << cnul.fail() << std::endl;
cnul << "Goodbye World!" << std::endl;
std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
The simplest solution is just to output to an unopened std::ofstream
(or any other output stream in an error state). This will result in the
stream being permanently in an error state. This could be an advantage
(<< operators will skip the formatting), but if any code that you
can't control checks for errors, and does something particular if they
occur, you'll likely have problems.
Otherwise, it's pretty simple to implement a null stream; the only
streambuf function you really have to override is overflow.
Something like the following should do the trick:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[64];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
return (c == EOF) ? '\0' : c ;
}
};
(The buffer will avoid some unnecessary virtual function calls. On some
platforms, this makes a significant difference.)
Then create an output stream which uses it:
class NulOStream : public NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
};
(The use of inheritance, rather than containment, ensures that the
streambuf is fully constructed before being passed to the ostream.
This generally isn't necessary in practice, but the standard doesn't
seem to authorize passing a not yet constructed streambuf to the
constructor of ostream.)
Simplest solution: Use a std::stringstream.
#include <sstream>
#include <iostream>
void func(std::ostream& o){
o << "blatest\n";
}
int main(){
std::stringstream black_hole;
func(std::cout);
func(black_hole);
}
The stringstream will contain the output, but if you don't use it, it's the same as if it was never filled.
Since nobody mentioned it, if it's about suppressing std or error output, you can simply close the corresponding file descriptors (e.g. fclose (stdout) or fclose (stderr)).
That will shup up everything, including things like printf or fprintf (stderr, ...)
So you will indeed keep using the usual cout or cerr, but they will be turned into bit buckets.
Some suggestions here: http://bytes.com/topic/c/answers/589209-std-null-stream
A good answer from that site:
Use ordinary std::fstream, open it only for writing to required file
"/dev/null". It should work.
If you really want to create own stream, just derive it from
basic_ostream and simply define your own operator<< to be function
which only returns stream reference. You will have to write dummy
'write' and 'put' method too (and all other methods for output).
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
From http://bytes.com/topic/c/answers/428285-null-ostream

Extension methods in c++

I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map can be used to associated methods with a class, but, the provided link seems to be dead. Does anyone know what that answer was referring to, or if there is another way to extend classes in a similar manner to extension methods (perhaps through some usage of mixins?).
I know the canonical C++ solution is to use free functions; this is more out of curiosity than anything else.
Different languages approach development in different ways. In particular C# and Java have a strong point of view with respect to OO that leads to everything is an object mindset (C# is a little more lax here). In that approach, extension methods provide a simple way of extending an existing object or interface to add new features.
There are no extension methods in C++, nor are they needed. When developing C++, forget the everything is an object paradigm --which, by the way, is false even in Java/C# [*]. A different mindset is taken in C++, there are objects, and the objects have operations that are inherently part of the object, but there are also other operations that form part of the interface and need not be part of the class. A must read by Herb Sutter is What's In a Class?, where the author defends (and I agree) that you can easily extend any given class with simple free functions.
As a particular simple example, the standard templated class basic_ostream has a few member methods to dump the contents of some primitive types, and then it is enhanced with (also templated) free functions that extend that functionality to other types by using the existing public interface. For example, std::cout << 1; is implemented as a member function, while std::cout << "Hi"; is a free function implemented in terms of other more basic members.
Extensibility in C++ is achieved by means of free functions, not by ways of adding new methods to existing objects.
[*] Everything is not an object.
In a given domain will contain a set of actual objects that can be modeled and operations that can be applied to them, in some cases those operations will be part of the object, but in some other cases they will not. In particular you will find utility classes in the languages that claim that everything is an object and those utility classes are nothing but a layer trying to hide the fact that those methods don't belong to any particular object.
Even some operations that are implemented as member functions are not really operations on the object. Consider addition for a Complex number class, how is sum (or +) more of an operation on the first argument than the second? Why a.sum(b); or b.sum(a), should it not be sum( a, b )?
Forcing the operations to be member methods actually produces weird effects --but we are just used to them: a.equals(b); and b.equals(a); might have completely different results even if the implementation of equals is fully symmetric. (Consider what happens when either a or b is a null pointer)
Boost Range Library's approach use operator|().
r | filtered(p);
I can write trim for string as follows in the same way, too.
#include <string>
namespace string_extension {
struct trim_t {
std::string operator()(const std::string& s) const
{
...
return s;
}
};
const trim_t trim = {};
std::string operator|(const std::string& s, trim_t f)
{
return f(s);
}
} // namespace string_extension
int main()
{
const std::string s = " abc ";
const std::string result = s | string_extension::trim;
}
This is the closest thing that I have ever seen to extension methods in C++. Personally i like the way it can be used, and possibly this it the closest we can get to extension methods in this language. But there are some disadvantages:
It may be complicated to implement
Operator precedence may be not that nice some times, this may cause surprises
A solution:
#include <iostream>
using namespace std;
class regular_class {
public:
void simple_method(void) const {
cout << "simple_method called." << endl;
}
};
class ext_method {
private:
// arguments of the extension method
int x_;
public:
// arguments get initialized here
ext_method(int x) : x_(x) {
}
// just a dummy overload to return a reference to itself
ext_method& operator-(void) {
return *this;
}
// extension method body is implemented here. The return type of this op. overload
// should be the return type of the extension method
friend const regular_class& operator<(const regular_class& obj, const ext_method& mthd) {
cout << "Extension method called with: " << mthd.x_ << " on " << &obj << endl;
return obj;
}
};
int main()
{
regular_class obj;
cout << "regular_class object at: " << &obj << endl;
obj.simple_method();
obj<-ext_method(3)<-ext_method(8);
return 0;
}
This is not my personal invention, recently a friend of mine mailed it to me, he said he got it from a university mailing list.
The short answer is that you cannot do that. The long answer is that you can simulate it, but be aware that you'll have to create a lot of code as workaround (actually, I don't think there is an elegant solution).
In the discussion, a very complex workaround is provided using operator- (which is a bad idea, in my opinion). I guess that the solution provided in the dead link was more o less similar (since it was based on operator|).
This is based in the capability of being able to do more or less the same thing as an extension method with operators. For example, if you want to overload the ostream's operator<< for your new class Foo, you could do:
class Foo {
friend ostream &operator<<(ostream &o, const Foo &foo);
// more things...
};
ostream &operator<<(ostream &o, const Foo &foo)
{
// write foo's info to o
}
As I said, this is the only similar mechanism availabe in C++ for extension methods. If you can naturally translate your function to an overloaded operator, then it is fine. The only other possibility is to artificially overload an operator that has nothing to do with your objective, but this is going to make you write very confusing code.
The most similar approach I can think of would mean to create an extension class and create your new methods there. Unfortunately, this means that you'll need to "adapt" your objects:
class stringext {
public:
stringext(std::string &s) : str( &s )
{}
string trim()
{ ...; return *str; }
private:
string * str;
};
And then, when you want to do that things:
void fie(string &str)
{
// ...
cout << stringext( str ).trim() << endl;
}
As said, this is not perfect, and I don't think that kind of perfect solution exists.
Sorry.
To elaborate more on #Akira answer, operator| can be used to extend existing classes with functions that take parameters too. Here an example that I'm using to extend Xerces XML library with find functionalities that can be easily concatenated:
#pragma once
#include <string>
#include <stdexcept>
#include <xercesc/dom/DOMElement.hpp>
#define _U16C // macro that converts string to char16_t array
XERCES_CPP_NAMESPACE_BEGIN
struct FindFirst
{
FindFirst(const std::string& name);
DOMElement * operator()(const DOMElement &el) const;
DOMElement * operator()(const DOMElement *el) const;
private:
std::string m_name;
};
struct FindFirstExisting
{
FindFirstExisting(const std::string& name);
DOMElement & operator()(const DOMElement &el) const;
private:
std::string m_name;
};
inline DOMElement & operator|(const DOMElement &el, const FindFirstExisting &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement &el, const FindFirst &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement *el, const FindFirst &f)
{
return f(el);
}
inline FindFirst::FindFirst(const std::string & name)
: m_name(name)
{
}
inline DOMElement * FindFirst::operator()(const DOMElement &el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline DOMElement * FindFirst::operator()(const DOMElement *el) const
{
if (el == nullptr)
return nullptr;
auto list = el->getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline FindFirstExisting::FindFirstExisting(const std::string & name)
: m_name(name)
{
}
inline DOMElement & FindFirstExisting::operator()(const DOMElement & el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
throw runtime_error(string("Missing element with name ") + m_name);
return static_cast<DOMElement &>(*list->item(0));
}
XERCES_CPP_NAMESPACE_END
It can be used this way:
auto packetRate = *elementRoot | FindFirst("Header") | FindFirst("PacketRate");
auto &decrypted = *elementRoot | FindFirstExisting("Header") | FindFirstExisting("Decrypted");
You can enable kinda extension methods for your own class/struct or for some specific type in some scope. See rough solution below.
class Extensible
{
public:
template<class TRes, class T, class... Args>
std::function<TRes(Args...)> operator|
(std::function<TRes(T&, Args...)>& extension)
{
return [this, &extension](Args... args) -> TRes
{
return extension(*static_cast<T*>(this), std::forward<Args>(args)...);
};
}
};
Then inherit your class from this and use like
class SomeExtensible : public Extensible { /*...*/ };
std::function<int(SomeExtensible&, int)> fn;
SomeExtensible se;
int i = (se | fn)(4);
Or you can declare this operator in cpp file or namespace.
//for std::string, for example
template<class TRes, class... Args>
std::function<TRes(Args...)> operator|
(std::string& s, std::function<TRes(std::string&, Args...)>& extension)
{
return [&s, &extension](Args... args) -> TRes
{
return extension(s, std::forward<Args>(args)...);
};
}
std::string s = "newStr";
std::function<std::string(std::string&)> init = [](std::string& s) {
return s = "initialized";
};
(s | init)();
Or even wrap it in macro (I know, it's generally bad idea, nevertheless you can):
#define ENABLE_EXTENSIONS_FOR(x) \
template<class TRes, class... Args> \
std::function<TRes(Args...)> operator| (x s, std::function<TRes(x, Args...)>& extension) \
{ \
return [&s, &extension](Args... args) -> TRes \
{ \
return extension(s, std::forward<Args>(args)...); \
}; \
}
ENABLE_EXTENSIONS_FOR(std::vector<int>&);
This syntactic sugar isn't available in C++, but you can define your own namespace and write pure static classes, using const references as the first parameter.
For example, I was struggling using the STL implementation for some array operations, and I didn't like the syntaxis, I was used to JavaScript's functional way of how array methods worked.
So, I made my own namespace wh with the class vector in it, since that's the class I was expecting to use these methods, and this is the result:
//#ifndef __WH_HPP
//#define __WH_HPP
#include <vector>
#include <functional>
#include <algorithm>
namespace wh{
template<typename T>
class vector{
public:
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator, const std::function<T(T,T)> &functor){
T accumulator = accumulatorInitiator;
for(auto &element: array) accumulator = functor(element, accumulator);
return accumulator;
}
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator){
return wh::vector<T>::reduce(array, accumulatorInitiator, [](T element, T acc){return element + acc;});
}
static std::vector<T> map(const std::vector<T> &array, const std::function<T(T)> &functor){
std::vector<T> ret;
transform(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static std::vector<T> filter(const std::vector<T> &array, const std::function<bool(T)> &functor){
std::vector<T> ret;
copy_if(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static bool all(const std::vector<T> &array, const std::function<bool(T)> &functor){
return all_of(array.begin(), array.end(), functor);
}
static bool any(const std::vector<T> &array, const std::function<bool(T)> &functor){
return any_of(array.begin(), array.end(), functor);
}
};
}
//#undef __WH_HPP
I wouldn't inherit nor compose a class with it, since I've never been able to do it peacefully without any side-effects, but I came up with this, just const references.
The problem of course, is the extremely verbose code you have to make in order to use these static methods:
int main()
{
vector<int> numbers = {1,2,3,4,5,6};
numbers = wh::vector<int>::filter(numbers, [](int number){return number < 3;});
numbers = wh::vector<int>::map(numbers,[](int number){return number + 3;});
for(const auto& number: numbers) cout << number << endl;
return 0;
}
If only there was syntactic sugar that could make my static methods have some kind of more common syntax like:
myvector.map([](int number){return number+2;}); //...