Converting parameters when passing to functions (c++) - 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.

Related

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.

How to pass a variable number of arguments of varying types to functions in a C++11 function map?

I am attempting to learn C++11 and have started writing a program that reads a textfile into a vector of strings, then passes the vector to a function that will ask the user to select the name of the function they wish to apply to the vector.
I have a function map like so in C++11:
std::map<std::string, void(*)(std::vector<std::string>& v)> funcs
{
{"f1", f2},
{"f2", f2},
};
And I call it with the following function:
void call_function(std::vector<std::string>& v)
{
std::string func;
std::cout << "Type the name of the function: ";
std::cin >> func;
std::cout << "Running function: " << func << "\n";
funcs[func](v);
}
And two example functions would be:
void f1(std::vector<std::string>& v)
{
std::cout << "lol1";
}
void f2(std::vector<std::string>& v)
{
std::cout << "lol2";
}
As of right now, I am successfully able to pass my vector of strings to the functions by calling them from the function map, however, I want to be able to pass a variable number of arguments of varying types. What I want to be able to do is to change my functions to accept integer and string arguments, but not all of my functions will accept the same amount of arguments or arguments of the same type.
For example, I may want to allow one function that is in the map to accept a string and an integer as arguments while another function may only accept a single integer or a single string as the arguments.How can I accomplish this? I've been thus far unable to discover a means of passing variable arguments through map to my functions.
Is this possible with std::map? I was also looking into variadic templates in C++11, but I'm not really understanding them that well.
Can anyone provide any insight?
That could be perfectly achieved using variadic templates. For example:
template<typename... ARGS>
struct event
{
typedef void(*)(ARGS...) handler_type;
void add_handler(handler_type handler)
{
handlers.push_back(handler);
}
void raise_event(ARGS args...)
{
for(handler_type handler : handlers)
handler(args...);
}
private:
std::vector<handler_type> handlers;
};
void on_foo(int a,int b) { std::cout << "on foo!!! (" << a << "," << b << ")" << std::end; }
int main()
{
event<int,int> foo;
foo.add_handler(on_foo);
foo.raise_event(0,0);
}
This class represents an event. An event is really a set of callbacks of the specified signature (A function of two int parameters, in the example).

compile-time check with const char* (nullptr)

I have a template class that takes a string literal as parameter. The code works fine - but I've got one question, whether it is possible to use compile-time check to skip the generating of if (S) or else block body at all? (Something like the __if_exists or #if, traits, etc). I understand that I could have a specialized A<nullptr> that defines a different print() function, but also want to know whether there's other (more simple) ways of doing this. Thanks!
template<char const* S = nullptr>
class A
{
public:
void print()
{
if (S)
cout << S << endl;
else
cout << "nullptr" << endl;
}
};
In your case, can't you set the default value of S as "nullptr" or any other constant string? Of course, this works when you don't actually need S to be NULL, but it will skip the if check.
add a function,
constexpr const char* getStr(){
return S? S : "null";
}
then it becomes,
void print(){
std::cout << getStr() << std::endl;
}

<< operator overloading in C++ for logging purposes

I have a C++ class where I place many std::cout statements to print informative text messages about a mass of signals that this class is handling. My intentition is to redirect these text messages to a function named log. In this function, I have flag named mVerbose which defines if the log text should be printed. The content of this function is as follows:
void XXXProxy::log(std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
Then, the caller code snippet to this function is as follows:
std::stringstream logStr;
logStr << "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
log(logStr);
I would like to overload the << operator in my XXXProxy in a way that I can get rid of creating a std::stringstream object and calling the log function. I want to be able to log the text messages as below and let the << operator aggregate everything into:
<< "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
So I wouldlike to have an member << function that looks like:
void XXXProxy::operator << (std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
QUESTION
I am relatively a novice C++ developer and get lots of compilation errors when attemting to write the above stated like << operator. Could you please make some suggestions or direct me to some links for me to correctly implement this << operator. Thanks.
If you don't want to use std::cout directly and you want to have your own Log class, you could implement a simple wrapper providing the same interface of std::ostream: operator<<:
class Log {
private:
std::ostream& _out_stream;
//Constructor: User provides custom output stream, or uses default (std::cout).
public: Log(std::ostream& stream = std::cout): _out_stream(stream) {}
//Implicit conversion to std::ostream
operator std::ostream() {
return _out_stream;
}
//Templated operator>> that uses the std::ostream: Everything that has defined
//an operator<< for the std::ostream (Everithing "printable" with std::cout
//and its colleages) can use this function.
template<typename T>
Log& operator<< (const T& data)
{
_out_stream << data;
}
}
So if you implement std::ostream& operator>>(std::ostream& os , const YourClass& object) for your classes, you can use this Log class.
The advantage of this approach is that you use the same mechanism to make std::cout << your_class_object work, and to make the class work with the Log.
Example:
struct Foo
{
int x = 0; //You marked your question as C++11, so in class initializers
//are allowed.
//std::ostream::operator<< overload for Foo:
friend std::ostream& operator<<(std::ostream& os , const Foo& foo)
{
os << foo.x;
}
};
int main()
{
Log my_log;
Foo my_foo;
my_foo.x = 31415;
my_log << my_foo << std::endl; //This prints "31415" using std::cout.
}
Possible improvements:
You could write a extern const of class Log, and make the class implement a singleton. This allows you to access the Log everywhere in your program.
It's common in log outputs to have a header, like Log output (17:57): log message. To do that, you could use std::endl as a sentinel and store a flag that says when the next output is the beginning of a line (the beginning of a log message). Checkout the next answer for a complete and working implementation.
References:
std::ostream
operator<< for std::ostream
std::enable_if
std::is_same
decltype specifier
The timestamp of the example was only that, an example :).
But if you like that, we could try to implement it. Thankfully to C++11 and its STL's big improvements, we have an excellent time/date API: std::chrono
std::chronois based in three aspects:
Clocks
Durations
Time points
Also, chrono provides three types of clocks, std::system_clock, std::steady_clock , and std::high_resolution_clock. In our case, we use std::system_clock (We want access to the date-time, not meassuring precise time intervals).
For more info about std::chrono, checkout this awsome Bo Qian's youtube tutorial.
So if we have to implement a time stamp for our log header, we could do this:
EDIT: Like other good things, C++ templates are good tools until you overuse it.
Our problem was that std::endl is a templated function, so we cannot pass it directly to
annother templated function as parammeter (operator<< in our case), because the compiler cannot deduce std::endl template argumments directly. Thats the recurrent error "unresolved overloaded function type".
But there is a much simpler way to do this: Using an explicit overload of operator<< for std::endl only, and other templated for everything else:
class Log
{
private:
std::ostream& _out_stream;
bool _next_is_begin;
const std::string _log_header;
using endl_type = decltype( std::endl ); //This is the key: std::endl is a template function, and this is the signature of that function (For std::ostream).
public:
static const std::string default_log_header;
//Constructor: User passes a custom log header and output stream, or uses defaults.
Log(const std::string& log_header = default_log_header , std::ostream& out_stream = std::cout) : _log_header( log_header ) , _out_stream( out_stream ) , _next_is_begin( true ) {}
//Overload for std::endl only:
Log& operator<<(endl_type endl)
{
_next_is_begin = true;
_out_stream << endl;
return *this;
}
//Overload for anything else:
template<typename T>
Log& operator<< (const T& data)
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t( now ); //Uhhg, C APIs...
auto now_tm = std::localtime( &now_time_t ); //More uhhg, C style...
if( _next_is_begin )
_out_stream << _log_header << "(" << now_tm->tm_hour << ":" << now_tm->tm_min << ":" << now_tm->tm_sec << "): " << data;
else
_out_stream << data;
_next_is_begin = false;
return *this;
}
};
const std::string Log::default_log_header = "Log entry";
This code snippet works perfectly. I have pushed the complete implementation to my github account.
Reference:
std::chrono
std::chrono::system_clock
std::chrono::system_clock::now()
std::time_t
std::chrono::system_clock::to_time_t()
std::tm
std::localtime()

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.