Do you know how to perform a lazy evaluation of string, like in this D snippet:
void log(lazy string msg) {
static if (fooBarCondition)
writefln(…) /* something with msg */
}
Actually, the problem might not need laziness at all since the static if. Maybe it’s possible to discard char const* strings when not used? Like, in C++:
void log(char const *msg) {
#ifdef DEBUG
cout << … << endl; /* something with msg */
#else /* nothing at all */
#endif
}
Any idea? Thank you.
#ifdef DEBUG
#define log(msg) do { cout << … << endl; } while(0)
#else
#define log(msg) do { } while(0)
#endif
There are two ways to achieve laziness in C++11: macros and lambda expressions. Both are not "lazy" technically, but what is called "normal evaluation" (as opposed to "eager evaluation"), which mean that an expression might be evaluated any number of times. So if you are translating a program from D (or haskell) to C++ you will have to be careful not to use expressions with side effects (including computation time) in these expressions.
To achieve true laziness, you will have to implement memoizing, which is not that simple.
For simple logging, macros are just fine.
You could mix macros and lambdas to create this effect
you could have a type, lazy
template<class T>
class lazy {
...
}
and then you could have a LAZY wrapper that created one of these using a lambda
#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
All my_lazy_type needs is a constructor that accepts a std::function, and a an overload of operator() that evaluates and returns this. On each evaluation you can replace the thunk with a thunk that just returns the already computed value and thus it would only get computed once.
edit:
here is an example of what I am talking about. I would like however to point out that this is not a perfect example. it passes around a bunch of stuff by value in side the lazy which may completely defeat the purpose of doing this all in the first place. It uses mutable inside this because I need to be able to memoize the thunk in const cases. This could be improved in a lot of ways but it's a decent proof of concept.
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#define LAZY(E) lazy<decltype((E))>{[&](){ return E; }}
template<class T>
class lazy {
private:
struct wrapper {
std::function<T()> thunk;
wrapper(std::function<T()>&& x)
: thunk(std::move(x)) {}
wrapper(const std::function<T()>& x)
: thunk(x) {}
};
//anytime I see mutable, I fill a bit odd
//this seems to be warented here however
mutable std::shared_ptr<wrapper> thunk_ptr;
public:
lazy(std::function<T()>&& x)
: thunk_ptr(std::make_shared<wrapper>(std::move(x))) {}
T operator()() const {
T val = thunk_ptr->thunk();
thunk_ptr->thunk = [val](){return val;};
return val;
}
};
void log(const lazy<std::string>& msg) {
std::cout << msg() << std::endl;
}
int main() {
std::string hello = "hello";
std::string world = "world";
log(LAZY(hello + ", " + world + "!"));
return 0;
}
While Elazar's answer works, I prefer not to use macros for this (especially not ones with all-lowercase names).
Here is what I would do instead:
template<bool /* = false */>
struct logger_impl {
template<typename T>
static std::ostream & write(std::ostream & stream, T const &) {
return stream;
}
};
template<>
struct logger_impl<true> {
template<typename T>
static std::ostream & write(std::ostream & stream, T const & obj) {
return stream << obj;
}
};
template<typename T>
void log(T const & obj) {
#if defined(NDEBUG)
logger_impl<true>::write(std::cout, obj);
#else
logger_impl<false>::write(std::cout, obj);
#endif
}
Just my 2 cents.
Related
I have code that includes a generated file (I don't know in advance its content), there is just a convention upon which me and my users agreed on how to create this file so I can use it. This file looks like
#define MACRO0 "A"
#define MACRO1 "B"
#define MACRO2 "C"
...
I want to print all macros values. My current code looks like
#ifdef MACRO0
std::cout << "MACRO0 " << MACRO0 << std::endl;
#endif
#ifdef MACRO1
std::cout << "MACRO1 " << MACRO1 << std::endl;
#endif
#ifdef MACRO2
std::cout << "MACRO2 " << MACRO2 << std::endl;
#endif
My question is, how to iterate over the macros in the generated file so I don't need to duplicate my code so much
First of all, we know we can count on Boost.Preprocessor for our looping needs. However, the generated code must work on its own. Unfortunately, #ifdef cannot work as a result of macro expansion, so there's no way to generate the code in your question. Are we toasted?
Not yet! We can take advantage of the fact that your macros are all either nonexistent or a string literal. Consider the following:
using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));
We're taking advantage of our old friend the most vexing parse here. The second line can be interpreted in two ways depending on whether MACRO1 is defined. Without it, it is equivalent to:
char const *probe(char const *MACRO1);
... which is a function declaration where MACRO1 is the name of the parameter. But, when MACRO1 is defined to be "B", it becomes equivalent to:
char const *probe = (char const *) "B";
... which is a variable initialized to point at "B". We can then switch on the type of what we just produced to see if a substitution occured:
if(!std::is_function<decltype(probe)>::value)
std::cout << "MACRO1 " << probe << '\n';
We could make use of if constexpr here, but std::cout can output a function pointer (it converts it to bool) so the dead branch is valid, and the compiler is clever enough to completely optimize it out.
Finally, we come back to Boost.Preprocessor to generate all that stuff for us:
#define PRINT_IF_DEFINED(z, n, data) \
{ \
StrPtr probe(StrPtr(BOOST_PP_CAT(MACRO, n))); \
if(!std::is_function<decltype(probe)>::value) \
std::cout << "MACRO" BOOST_PP_STRINGIZE(n) " " << probe << '\n'; \
}
#define PRINT_MACROS(num) \
do { \
using StrPtr = char const *; \
BOOST_PP_REPEAT(num, PRINT_IF_DEFINED, ~) \
} while(false)
... voilà!
See it live on Coliru
Note: the Coliru snippet includes warning disablers for GCC and Clang, which warn against our poor pal the most vexing parse :(
I ran into the same kind of need a long time ago.
My solution was to use the preprocessor, but not to get the answer "within the code".
For example, clang++ -dM -E test.cpp will output all the macros. (At the time, I used gcc, but the same technique works for GCC, CLang, and Visual Studio's CL.EXE ... the compiler switches may vary.)
Ahh, drat, that also includes all the predefined macros.
So I would produce a "blacklist" file of the predefined macros that I did not care about, and then use that to filter out those results (using grep -v).
The other problem I ran into was that sometimes someone would #undef IMPORTANT_MACRO which would then get missed in the dump. For those infrequent situations... and then the murders began.
This answer is written taking a follow-up question into account.
C++ has support for generic programming that often eliminates need for preprocessor. In this case it would be better to make a set of type traits declaring properties of parameters that need to be handled reducing role of preprocessor to conditional compilation (or eliminating it completely if this code is supposed to be generated every time):
enum class
t_Param
{
begin, a = begin, b, c, d, e, z, end
};
template<t_Param param, typename TEnabled = void> class
t_ParamIsEnabled final: public ::std::true_type
{};
template<t_Param param> class
t_ParamIsEnabled
<
param
, typename ::std::enable_if
<
(t_Param::end == param)
#ifndef A1
|| (t_Param::a == param)
#endif
#ifndef B2
|| (t_Param::b == param)
#endif
#ifndef C3
|| (t_Param::c == param)
#endif
#ifndef D4
|| (t_Param::d == param)
#endif
#ifndef E5
|| (t_Param::e == param)
#endif
>::type
> final: public ::std::false_type
{};
template<t_Param param> class
t_ParamTrait;
template<> class
t_ParamTrait<t_Param::a> final
{
public: static constexpr auto const & num{"1"};
public: static constexpr auto const & val{"A"};
};
template<> class
t_ParamTrait<t_Param::b> final
{
public: static constexpr auto const & num{"2"};
public: static constexpr auto const & val{"B"};
};
template<> class
t_ParamTrait<t_Param::c> final
{
public: static constexpr auto const & num{"3"};
public: static constexpr auto const & val{"C"};
};
template<> class
t_ParamTrait<t_Param::d> final
{
public: static constexpr auto const & num{"4"};
public: static constexpr auto const & val{"D"};
};
template<> class
t_ParamTrait<t_Param::e> final
{
public: static constexpr auto const & num{"5"};
public: static constexpr auto const & val{"E"};
};
template<> class
t_ParamTrait<t_Param::z> final
{
public: static constexpr auto const & num{"26"};
public: static constexpr auto const & val{"ZZ"};
};
This will allow you to iterate over parameters and query their properties using generic code:
template<t_Param param> typename ::std::enable_if<t_ParamIsEnabled<param>::value>::type
Echo(void)
{
::std::cout << t_ParamTrait<param>::val << ":" << t_ParamTrait<param>::num << ::std::endl;
}
template<t_Param param> typename ::std::enable_if<!t_ParamIsEnabled<param>::value>::type
Echo(void)
{
// Do nothing
}
template<int param_index = 0> void
Echo_All(void)
{
Echo<static_cast<t_Param>(param_index)>();
Echo_All<param_index + 1>();
}
template<> void
Echo_All<static_cast<int>(t_Param::end)>(void)
{
// Do nothing.
}
int main()
{
Echo_All();
return 0;
}
online compiler
I am writing a C++ wrapper for a C library that works with handles represented by integers. There are a bunch of open functions (Aopen, Bopen, Copen, Dopen, Eopen, ...) and corresponding close functions (Aclose, Bclose, Cclose, Dclose, Eclose, ...). I currently have wrapper classes implementing basic RAII, but I have a bit of code duplication, as each of these wrappers differs only in which open and close routine it calls. To get rid of this duplication I was thinking of templating on an enum I define with values for each of the routines (e.g. Atype, Bytpe, etc), and then selecting the correct open and close function at compile time. It would like something like:
TypeWrapper<AType> wrapped_a(...)
TypeWrapper<BType> wrapped_b(...)
...
Is this a reasonable approach, is there a simpler approach, or is there a name for this type of construction?
Thank you!
You may do something like the following:
template <typename H, H Open(const char*), void Close(H)>
class Wrapper
{
public:
Wrapper(const char* file) : h(Open(file)) {}
~Wrapper() { Close(h); }
Wrapper(const Wrapper&) = delete;
Wrapper& operator = (const Wrapper&) = delete;
private:
H h;
};
And then using Wrapper_A = Wrapper<AHandle, AOpen, AClose>;
Live example
What you're looking for is Template Specialization.
Basically, this is done by templating your TypeWrapper class on an enum value, then providing specialized implementations for the open/close calls for each enum value.
An example is worth a thousand words: live example
#include <iostream>
using namespace std;
enum Type {
AType = 0,
BType,
CType,
};
void AOpen() { std::cout << "A open." << std::endl; }
void BOpen() { std::cout << "B open." << std::endl; }
void COpen() { std::cout << "C open." << std::endl; }
template<Type T>
class TypeWrapper {
public:
void open();
void close();
};
template<>
void TypeWrapper<AType>::open() { AOpen(); }
template<>
void TypeWrapper<BType>::open() { BOpen(); }
template<>
void TypeWrapper<CType>::open() { COpen(); }
int main() {
TypeWrapper<AType> wrapped_a;
TypeWrapper<BType> wrapped_b;
wrapped_a.open();
wrapped_b.open();
return 0;
}
It is my very first post, so I would like to welcome with everybody. The problem I have occurred is the code optimization at compilation time, and to be more specific removing debug prints.
Let's imagine that we have native syslog logger and we are wrapping it (without using of macros, it is very important note!) with following code:
enum severity { info_log, debug_log, warning_log, error_log };
template <severity S>
struct flusher {
logger* log_;
flusher(logger* log) : log_(log) {}
flusher(flusher& rhs) : log_(rhs.log_) {}
~flusher() { syslog(S, log_->stream.str()); log_->stream.str(""); }
operator std::ostream& () { return log_->stream; }
};
#ifdef NDEBUG
template <> struct flusher<debug_log> {
flusher(logger*) {}
flusher(flusher&) {}
~flusher() {}
template <typename T> flusher& operator<<(T const&) { return *this; }
};
#endif
struct logger {
std::ostringstream stream;
template <severity T>
flusher<T> operator<<(flusher<T> (*m)(logger&)) { return m(*this); }
};
inline flusher<info_log> info(logger& log) { return flusher<info_log>(&log); }
inline flusher<debug_log> debug(logger& log) { return flusher<debug_log>(&log); }
inline flusher<warning_log> warning(logger& log) { return flusher<warning_log>(&log); }
inline flusher<error_log> error(logger& log) { return flusher<error_log>(&log); }
I thought that the empty implementation of flusher will encourage compiler to remove such useless code, but with both O2 and O3 it is not removed.
Is there any possibility to provoke mentioned behaviour?
Thanks in advance
I have successfully done what you're attempting, although with at least two differences... 1) I wasn't using templates - that might be creating a complexity the compiler is unable to optimize out, and 2) my log use included a macro (see below).
Additionally, you may have already done this, make sure all your "empty" definitions are in the logger's header file (so optimizations are done at compile-time and not postponed to link-time).
// use it like this
my_log << "info: " << 5 << endl;
The release definition looks like this:
#define my_log if(true);else logger
and the debug definition looks like this:
#define my_log if(false);else logger
Note that the compiler optimizes out the logger for all if(true) in release, and uses the logger in debug. Also note the full if/else syntax in both cases avoids funny situations where you have unscoped use, e.g.
if (something)
my_log << "this" << endl;
else
somethingelse();
would cause somethingelse to be the else of my_log without it.
Your current code is not preventing the call to f() and any side effects it may have, only preventing the actual printing. This is why macros are the traditional approach to this problem - they provide an unevaluated context where you can check if the value should be printed before actually printing.
In order to achieve this without macros, some extra indirection is needed e.g. std::function, function pointers etc. As an example, you could provide a wrapper class which contained a std::function, and specialise your stream operators to call the std::function in the default case, and not in the NDEBUG case
Very rough example:
//Wrapper object for holding std::functions without evaluating
template <typename Func>
struct debug_function_t {
debug_function_t(Func & f) : f(f) {}
decltype(f()) operator()() { return f(); }
std::function<Func> f;
};
//Helper function for type deduction
template <typename Func>
debug_function_t<Func> debug_function(Func & f) {
return debug_function_t<Func>(f);
}
struct debug_logger {
template <typename T>
debug_logger & operator<<(T & rhs) {}
template <typename Func> //Doesn't call f(), so it's never evaluated
debug_logger & operator<<(debug_function_t<Func> f) { }
};
Then in your client code
int f(){ std::cout << "f()\n"; }
debug_logger log;
log << debug_function(f);
So, following the comment's code:
inline int f()
{
std::cout << 1;
return 1;
}
needs to be made into:
inline int f()
{
#ifndef NDEBUG
std::cout << 1;
#endif
return 1;
}
or something like this:
#ifndef NDEBUG
static const int debug_enable = 1;
#else
static const int debug_enable = 0;
#endif
inline int f()
{
if (debug_enable)
{
std::cout << 1;
}
return 1;
}
You need to tell the compiler somehow that this code isn't needed.
The technique I've used for a few games requires the debug printing to be a function rather than a general expression. E.g.:
debug_print("this is an error string: %s", function_that_generates_error_string());
In release mode, the definition of debug_print is:
#define debug_print sizeof
That removes debug_print and any expression passed to it from the executable. It still has to be passed valid expressions, but they are not evaluated at runtime.
I'm trying to write a really simple thread-safe logger. Ideally, I wanted it to work just like std::cout, wherein you could just overload the << operator and have everything magically show up in the log. I'm on a Windows machine, so here's the approach I tried:
// Threadsafe logger
class Logger
{
public:
Logger()
{
InitializeCriticalSection(&s);
}
~Logger()
{
DeleteCriticalSection(&s);
}
void Log(std::ostream const& os)
{
EnterCriticalSection(&s);
//std::cout << static_cast<std::stringstream const&>(os).str();
std::cout << os.rdbuf();
LeaveCriticalSection(&s);
}
private:
CRITICAL_SECTION s;
};
Notice that I've tried two approaches to the Log() function. The reason I accept an ostream is because that's what a stringstream seems to produce after the << operator is called. Both variants of the Log() function fail in the same way when I run this code:
#include <iostream>
#include <sstream>
#include <Windows.h>
int main(int argc, char* argv[])
{
Logger logger;
//logger.Log(std::stringstream("Test"));
logger.Log(std::stringstream("Another ") << "test");
std::cin.get();
}
Outputting the first line ("Test") works correctly and displays properly using both variants of the Log function. The second line outputs a mangled output:
testher
which is obviously test written over Another. What am I missing about the way these streams work? I tried making a flush call hoping that would fix things, but it did nothing.
How can I get this attempt at a thread-safe logger working correctly with the streams?
Using variadic templates:
void Log_impl(std::ostream &os) {} // recursion base case
template<typename T,typename... Us>
void Log_impl(std::ostream &os,T &&t,Us &&... us) {
os << std::forward<T>(t);
Log_impl(os,std::forward<Us>(us)...);
}
template<typename... Ts> void Log(Ts &&... ts) {
std::stringstream ss;
Log_impl(ss,std::forward<Ts>(ts)...);
fprintf(stdout,"%s\n",ss.str().c_str()); // thread safe output
}
usage:
Log("Another"," test ",100);
I haven't actually tested this code...
At least in my opinion, this approach to the problem is at least somewhat clumsy to use, since it requires you to create an auxiliary ostream object of some sort, stream data into it, and then pass that to your log. That doesn't seem to fit very closely with what you've said you'd really prefer.
I'm also a bit less than excited about how you've done your thread-locking code. Just for example, if you get an exception during your std::cout << os.rdbuf();, you can exit the scope without leaving the critical section.
I think I'd start with a thin wrapper around a critical section, add an RAII-style class to lock the critical section (and automatically unlock it when it goes out of scope), then use those in implementing the Log class. Further, I'd cheat and have the Log class use a template member function to accept almost any type of output in one fell swoop:
Edit: After some more thought, I've decided to embrace the notion that every problem can be solved with another level of indirection. To do that, I've added an intermediate transaction that encapsulates chaining the output of a number of items into a stringstream, then writing out that result as a thread-safe transaction.
#include <windows.h>
#include <iostream>
#include <sstream>
class crit_sect {
CRITICAL_SECTION cs;
void lock() { EnterCriticalSection(&cs); }
void unlock() { LeaveCriticalSection(&cs); }
friend class lock;
crit_sect(crit_sect const &); /* = delete; */
crit_sect &operator=(crit_sect const &other); /* = delete; */
public:
crit_sect() { InitializeCriticalSection(&cs); }
~crit_sect() { DeleteCriticalSection(&cs); }
};
class lock {
crit_sect &cs;
public:
lock(crit_sect &c) : cs(c) { cs.lock(); }
~lock() { cs.unlock(); }
};
class transaction {
std::ostringstream buffer;
public:
transaction(std::string const &s="") : buffer(s, std::ios::out | std::ios::ate) {}
template <class T>
transaction &operator<<(T const &t) {
buffer << t;
return *this;
}
friend std::ostream &operator<<(std::ostream &os, transaction const &t) {
return os << t.buffer.str();
}
};
class Log {
std::ostream &out;
crit_sect mutex;
public:
Log(std::ostream &sink) : out(sink) { }
template <class T>
void operator<<(T const &t) {
lock l(mutex);
out << t;
}
};
int main() {
Log l(std::cout);
l << "This is a string\n";
l << (transaction("Another ") << "Test");
return 0;
}
Since the log type doesn't support chaining, any attempt at chaining the output without using a transaction will fail (won't compile). Compared to the original, usage is still a bit cleaner though -- the extra parameters needed for the ostringstream ctor are hidden, and the name transaction clarifies what is being done, or rather, accomplished.
The problem isn't with the logger, rather it's with your use of stringstream.
When std::stringstream is initialized, the stream's position indicator is positioned at the beginning of the stream.
Now when you start writing to the string using '<<', you start writing at the position indicator, replacing whatever was there before.
To work around this, you can initialize the stringstream with
std::stringstream("Another ", stringstream::in | stringstream::out | std::stringstream::ate)
(as per http://www.cplusplus.com/reference/iostream/stringstream/stringstream/ )
<< doesn't send the null byte at the end of "test" into the temporary stringstream("Another ") you created, which is why you see "testher".
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;}); //...