C++ enhanced cat - c++

Suppose I have a function from string to string, such as for example:
string identity(string text) {
return text;
}
How can I print the function applied to input to output, avoiding explicit variables, input and output handling? Something like interact in Haskell.
int main() {
std::interact(identity);
}
This would really cut down obvious code, and let the algoritmh and the logic stand out instead.
Example usage would be:
$./enhanced_cat
Example
Example
$

You can easily write such a thing yourself using std::function. Example:
#include <string>
#include <iostream>
#include <functional>
std::string identity(std::string const& text) {
return text;
}
void interact(std::function<std::string(std::string const&)> f)
{
std::string input;
std::getline(std::cin, input);
std::cout << f(input);
}
int main()
{
interact(identity);
}
But that certainly doesn't look like idiomatic C++. Even though C++ supports functional programming to a certain extent, it's not a functional programming language, and you should not try to write Haskell in C++.

template<class F>
struct interacter_t {
F f;
void operator()( std::istream& is = std::cin, std::ostream& os = std::cout ) {
std::string in;
while( getline( is, in ) ) {
os << f(std::move(in)) << '\n';
}
}
};
template<class F>
interacter_t<std::decay_t<F>> interact( F&& f ) {
return {std::forward<F>(f)};
}
then:
int main() {
auto io = interact(identity);
std::cout << "Start:\n";
io();
std::cout << "End.\n";
}
I added the separate invocation to creation of the interactor object.
You can do it on one line:
std::cout << "Start:\n";
interact(identity)();
std::cout << "End.\n";
or you can modify interact to run the interactor_t instead of returning it. I personally like that distinction: creation and execution are different things.
live example.
This version reads everything from the input stream until it ends. Reading less than that is easy, just replace the body of operator().

You could roll your own interact, something like the below. (Note: probably won't actually compile as is.)
void interact(string (*function)(string))
{
string input;
getline(cin, input);
cout << function(input) << endl;
}

Related

How can I inject a newline when a std::ostream object is std::flush'ed?

How can I minimally wrap a std::ofstream so that any call to sync (std::flush) gets turned into a call to std::endl.
(everything below is an answer to the question "why would you do that?" and is not relevant to the above question)
I have an application which contains a custom std::ostream implementation (which wraps around zmq), let's call it zmq_stream.
This zmq_stream also internally implements a custom streambuffer, and works very nicely.
One of the motivations of this design is that in my unit tests, I can simply swap out the zmq_stream in my unit tests with a regular old std::ostringstream and test the results, completely hiding out the network layer.
One of the features of the application itself is to redirect application output to a file or stdout via a command line flag.
Once again, using a basic switch at startup, I can pass either zmq_stream, std::ofstream or plain old std::cout to my main loop.
This is accomplished something like this:
std::ostream* out;
switch(cond)
{
case 1:
out = &std::cout;
break;
case 2:
out = new ofstream("file");
break;
case 3:
out = new zmq_stream(method, endpoints);
break;
}
main_loop(out);
The usage of zmq_stream is as follows:
zmq_stream out(method, endpoints);
out << "do something " << 42 << " or other";
out << "and another" << std::flush; // <- full constructed buffer is sent over the network
Note: it is by design that I use std::flush and not std::endl when flushing to the network. I do not wish to append a newline to all of my network transmissions. As such, all network outputs by the application use std::flush and not std::endl and changing this is not the correct answer.
Question: while for testing purposes, everything works as expected, for the std::cout and std::ofstream options, I'd like to be able to inject a newline when std::flush is called, so that my network transmissions can be separated into newlines on stdout. This would allow me to pipe them onto the standard posix suite of tooling...
Without this injection, there is no way to determine (aside from timing) where the network boundaries are.
I'm looking for the most minimal possible override here so that I don't have to write out a bunch of new classes. Ideally, overriding the sync() virtual method so that it calls overflow('\n'); and then calls base sync().
However, this is proving to be much more challenging than I expected, so I'm wondering if I'm doing it wrong.
The initial solution I wrote doesn't work because it is a compile time solution and I can't switch on it without re-implementing inheritance (so that the main_loop function gets a base class as a parameter).
Instead, here's the answer to original problem implemented in what appears to be the most minimal way possible.
#include <iostream>
#include <fstream>
#include <iomanip>
typedef std::ostringstream zmq_stream;
template <class T>
class newline_injector_streambuf: public std::basic_streambuf<T> {
public:
using int_type = typename std::basic_streambuf<T>::int_type;
newline_injector_streambuf(std::basic_streambuf<T>& dest) : sink(dest) {}
protected:
virtual int_type sync() override { overflow('\n'); return sink.pubsync(); }
virtual int_type overflow(int_type c) override { return sink.sputc(c); }
std::basic_streambuf<T>& sink;
};
template <class T>
struct newline_injector_stream : public std::basic_ostream<typename T::char_type> {
newline_injector_streambuf<typename T::char_type> buf;
newline_injector_stream(T* file) : buf(*file->rdbuf())
{
std::basic_ostream<typename T::char_type>::rdbuf(&buf);
}
};
void test(std::ostream& out)
{
out << std::setfill('x') << std::setw(10) << "" << std::flush;
out << "Hello, world!" << std::flush << "asdf" << std::endl;
}
int main() {
newline_injector_stream out1(&std::cout);
newline_injector_stream out2(new std::ofstream("test.output", std::ios::out | std::ios::ate));
test(std::cout);
test(out1);
test(out2);
return 0;
}
This is the solution that was devised thanks to #463035818-is-not-a-number's initial answer:
struct zmq_stream;
template<typename T>
struct output_device {
T& output;
output_device(T& backing_stream) : output(backing_stream){}
template <typename U>
output_device& operator<<(const U& u)
{
output << u;
return *this;
}
output_device& operator<<(std::ostream& (*f)(std::ostream&)) {
if constexpr (!std::is_same<T, zmq_stream>::value)
if (f == &std::flush<std::ostream::char_type,std::ostream::traits_type>)
output << "\n";
output << f;
return *this;
}
};
// Usage:
int main()
{
/* prelude code */
auto out1 = output_device(std::cout);
auto out2 = output_device(std::ofstream("filename"));
auto out3 = output_device(zmq_stream(method, endpoints));
out1 << "foo" << std::flush << "bar"; // results in foo\nbar
out2 << "foo" << std::flush << "bar"; // results in foo\nbar
out3 << "foo" << std::flush << "bar"; // results in foobar
}
template <class T>
class separator: public std::basic_streambuf<T> {
public:
using int_type = typename std::basic_streambuf<T>::int_type;
using char_type = typename std::basic_streambuf<T>::char_type;
using traits_type = typename std::basic_streambuf<T>::traits_type;
separator(std::basic_streambuf<T> *dest) : sink(dest) {}
protected:
virtual int_type sync() override {
if (nullptr == sink)
return 1;
//std::basic_streambuf<T>::overflow('\n');
overflow('\n');
return sink->pubsync();
}
virtual int_type overflow(int_type c) override {
if (sink == nullptr)
return 1;
return sink->sputc(c);
}
std::basic_streambuf<T> *sink = nullptr;
};
template <class T> struct newline_injector_stream : public std::basic_ostream<T> {
separator<T> buf;
public:
newline_injector_stream(std::basic_ostream<T> &file) : buf(file.rdbuf())
{
std::basic_ostream<T>::rdbuf(&buf);
}
};
The main_loop function signature now goes from taking a std::ostream* type to a output_device& type.

Log anything i want using auto keyword

I programmed a log class that logs messages in color in the terminal. I want it to be able to log anything
I give it to log. I guess templates are the way to go. But can't i use auto as an argument type, then check if it is a string and if not call the tostring method of the object ?
Since c++20 you can use auto and overload for the other types you want to handle differently.
void log(auto test) {
std::cout << std::to_string(test) << std::endl;
}
void log(const std::string &str) {
std::cout << "str: " << str << std::endl;
}
int main()
{
log(std::string("test"));
log(10);
}
You could indeed use templates, then just add a template specialization for std::string that doesn't invoke std::to_string
#include <iostream>
#include <string>
template <typename T>
void ToLog(T t)
{
std::cout << std::to_string(t) << '\n';
}
template <>
void ToLog<std::string>(std::string str)
{
std::cout << str << '\n';
}
int main()
{
ToLog(5);
ToLog(12.0);
ToLog(std::string("hello"));
return 0;
}
Output
5
12.000000
hello
No, auto needs to determine the type of a variable in compile time, which can't be done until C++20. If you are using C++ standard, either you use templates, preprocessor macros (as some logging libraries do) or directly some to_string function before passing the argument.
But, as said, with C++20 it can be done, and behaves like a template.
You might find this question useful.

Converting parameters when passing to functions (c++)

I am just starting to teach myself C++ and am having a hard time with function parameter passing. For example I am using my own print function where you simply put the string into the parameters and it logs it to the console.
//Print Function
void print(std::string message = "") {
std::cout << message << std::endl;
}
However because I declare it as a std::string variable if I pass it a number it will not print it. Ultimately I would like to make an input and print system like in Python. How to I go about this? Is there a way to convert the parameters to string? Or some other solution. Another function with similar problems is my input function:
//Input function (Enter does not work without text, space is not text)
std::string input(const char* message = "") {
std::cout << message;
std::string x;
std::cin >> x;
return x;
}
This does not allow the return to be an int witch makes calculations using the input harder. Any help is appreciated thanks in advance!
~ Moses
Besides template, if your compiler supports C++14, You can also use auto with lambda function. You can just write all these inside the main function.
auto print = [](const auto& message) {std::cout << message << std::endl;};
print(1); //1
print("AAA"); //AAA
Note that, unlike Python, when you want to print something, you don't need to convert it to a string first. As long as the thing you want to print has overloaded cout, You can simply cout it. And using template or auto doesn't change the fact that everything in C++ is statically typed, it's just that the compiler will create the different versions of overload functions for you automatically.
EDIT
As #Peter pointed out in the comment section, saying "cout is something that can be overloaded is flat-out wrong", and more accurate to say overloading the operator<< for the ostream and the corresponding class
Can++ templates are useful there.
//Print Function
template <typename T>
void print(const T& message) {
std::cout << message << std::endl;
}
void print() {
std::cout << std::endl;
}
Note, I removed a default argument value and used overloaded function. With passed empty argument type of template parameter can not be deduced. print does not work with containers and you need more efforts to print containers, in Python it works from box.
//Input function (Enter does not work without text, space is not text)
template <typename T>
T input(const char* message = "")
{
std::cout << message;
T x;
std::cin >> x;
return x;
}
Usage: int n = input<int>("Input number:");.
Alternatively I discovered a way to do this without using lambda:
void print(int message) {
std::cout << message << std::endl;
};
void print(float message) {
std::cout << message << std::endl;
};
void print(std::string message) {
std::cout << message << std::endl;
};
By making multiple functions with the same name it will use what ever one works, so any input (3.14, 8, "Hello") will all work and use corresponding function.

C++ Using stringstream after << as parameter

Is it possible to write a method that takes a stringstream and have it look something like this,
void method(string str)
void printStringStream( StringStream& ss)
{
method(ss.str());
}
And can be called like this
stringstream var;
printStringStream( var << "Text" << intVar << "More text"<<floatvar);
I looked up the << operator and it looks like it returns a ostream& object but I'm probably reading this wrong or just not implementing it right.
Really all I want is a clean way to concatenate stuff together as a string and pass it to a function. The cleanest thing I could find was a stringstream object but that still leaves much to be desired.
Notes:
I can't use much of c++11 answers because I'm running on Visual Studio 2010 (against my will, but still)
I have access to Boost so go nuts with that.
I wouldn't be against a custom method as long as it cleans up this mess.
Edit:
With #Mooing Duck's answer mixed with #PiotrNycz syntax I achieved my goal of written code like this,
try{
//code
}catch(exception e)
{
printStringStream( stringstream() << "An exception has occurred.\n"
<<" Error: " << e.message
<<"\n If this persists please contact "<< contactInfo
<<"\n Sorry for the inconvenience");
}
This is as clean and readable as I could have hoped for.
Hopefully this helps others clean up writing messages.
Ah, took me a minute. Since operator<< is a free function overloaded for all ostream types, it doesn't return a std::stringstream, it returns a std::ostream like you say.
void printStringStream(std::ostream& ss)
Now clearly, general ostreams don't have a .str() member, but they do have a magic way to copy one entire stream to another:
std::cout << ss.rdbuf();
Here's a link to the full code showing that it compiles and runs fine http://ideone.com/DgL5V
EDIT
If you really need a string in the function, I can think of a few solutions:
First, do the streaming seperately:
stringstream var;
var << "Text" << intVar << "More text"<<floatvar;
printStringStream(var);
Second: copy the stream to a string (possible performance issue)
void printStringStream( ostream& t)
{
std::stringstream ss;
ss << t.rdbuf();
method(ss.str());
}
Third: make the other function take a stream too
Make your wrapper over std::stringstream. In this new class you can define whatever operator << you need:
class SSB {
public:
operator std::stringstream& () { return ss; }
template <class T>
SSB& operator << (const T& v) { ss << v; return *this; }
template <class T>
SSB& operator << (const T* v) { ss << v; return *this; }
SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
// Be aware - I am not sure I cover all <<'s
private:
std::stringstream ss;
};
void print(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
int main() {
SSB ssb;
print (ssb << "Hello" << " world in " << 2012 << std::endl);
print (SSB() << "Hello" << " world in " << 2012 << std::endl);
}
For ease of writing objects that can be inserted into a stream, all these classes overload operator<< on ostream&. (Operator overloading can be used by subclasses, if no closer match exists.) These operator<< overloads all return ostream&.
What you can do is make the function take an ostream& and dynamic_cast<> it to stringstream&. If the wrong type is passed in, bad_cast is thrown.
void printStringStream(ostream& os) {
stringstream &ss = dynamic_cast<stringstream&>(os);
cout << ss.str();
}
Note: static_cast<> can be used, it will be faster, but not so bug proof in the case you passed something that is not a stringstream.
Since you know you've got a stringstream, just cast the return value:
stringstream var;
printStringStream(static_cast<stringstream&>(var << whatever));
Just to add to the mix: Personally, I would create a stream which calls whatever function I need to call upon destruction:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
It is worth noting that the first object sent to the temporary has to be of a specific set of types, namely one of those, the class std::ostream knows about: Normally, the shift operator takes an std::ostream& as first argument but a temporary cannot be bound to this type. However, there are a number of member operators which, being a member, don't need to bind to a reference! If you want to use a user defined type first, you need to extract a reference temporary which can be done by using one of the member input operators.

std::string and format string

I found the below code through Google. It almost does what I want it to do, except it doesn't provide a way to indicate the precision like '%.*f' does in C-type format strings. Also, it doesn't provide anything further than 5 decimal places. Am I going to have to stick with C strings and snprintf?
#include <string>
#include <sstream>
#include <iostream>
template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
{
std::ostringstream oss;
oss << f << t;
return oss.str();
}
int main()
{
std::cout<<to_string<double>(3.1415926535897931, std::dec)<<std::endl;
return 0;
}
You want to use the std::setprecision manipulator:
int main()
{
std::cout << std::setprecision(9) << to_string<long>(3.1415926535897931, std::dec)
<< '\n';
return 0;
}
C++ wouldn't be successful if it couldn't do something C could.
You need to check out manipulators.
If you want C-style formatting (which I do prefer, it's more terse), check out Boost.Format.
Have you looked at Boost::format?
Edit: It's not entirely clear what you want. If you just want to write to a string, with formatting, you can use normal manipulators on a stringstream. If you want to use printf-style formatting strings, but retain type-safety, Boost::format can/will do that.
Taking the almost-correct answer (note that std::dec is redundant in this simple case):
int main()
{
std::cout << std::setprecision(9) << std::dec << 3.1415926535897931 << std::endl;
return 0;
}
However, if you wanted the to_string function to behave as desired, that's a bit more difficult. You'd need to pass setprecision(9) to the to_string<T> function, and it doesn't accept arguments of that type. You'd want a templated version:
template <class T, class F>
std::string to_string(T t, F f)
{
std::ostringstream oss;
oss << f << t;
return oss.str();
}
int main()
{
std::cout << to_string<double>(3.1415926535897931, std::setprecision(9)) << std::endl;
return 0;
}
This works because you really didn't need std::dec in to_string. But if you needed to pass more manipulators, the simple solution is to add template <class T, class F1, class F2> std::string to_string(T t, F1 f1, F2 f2) etcetera. Technically this doesn't scale very well, but it's going to be so rare that you probably don't need it at all.